動態渲染頁面爬取

04- 動態渲染頁面爬取

4-1 Selenium的安裝

Selenium是一個自動化測試工具,利用它可以驅動瀏覽器執行特定的動作,如點擊、下拉等操作,同時還可以獲取瀏覽器當前呈現的頁面的源代碼,做到可見即可爬。對於一些JavaScipt動態渲染的頁面來說,此種抓取方式非常有效。

4 -2 Selenium相關鏈接

4-3 pip 安裝

pip install selenium

4-4 ChromeDriver 的安裝

安裝ChromeDriver。因爲只有安裝ChromeDriver.才能驅動Chrom瀏覽器完成相對應的操作

4-5 ChromeDriver 的相關鏈接

4-6 ChromeDriver環境配置

在Windows下,建議直接將chromedriver.exe文件拖到Python的根目錄下

在配置Python的時候系統會自動把Python配置到環境中,到時候我們可以直接使用驅動就可以不用寫路徑問題

4-7 Selenium聲明瀏覽器對象

Selenium支持多種的瀏覽器,如chrome、Firefox、Edge等

# @Time : 2020/5/11 15:01 
# @Author : SmallJ

# 支持的瀏覽器
from selenium import webdriver

browser = webdriver.Chrome()
borwser = webdriver.Android()
borwser = webdriver.Firefox()
borwser = webdriver.Ie()

4-8 Selenium訪問頁面

我們可以用get()方法來請求網頁,參數傳入鏈接URL即可。

  • get : 請求的網址
  • page_source : 爲反映頁面源代碼
  • close : 爲關閉瀏覽器
# @Time : 2020/5/11 15:01 
# @Author : SmallJ

# 支持的瀏覽器
from selenium import webdriver

# 實例化瀏覽器
browser = webdriver.Chrome()

# 用browser這個對象來發送請求
url = 'https://www.taobao.com/'
browser.get(url)

# page_source 爲頁面源代碼
# 用browser這個對象來獲取頁面源代碼
html = browser.page_source
print(html)

# close 爲關閉瀏覽器
browser.close()

4-9 Selenium查找節點

  • 單個節點
語法 描述
find_element_by_id 根據頁面中的id屬性來查找值
find_element_by_xpath 根據xpath語法來進行查找值
find_element_by_link_text 根據文本來進行查詢
find_element_by_partial_link_text 根據文本進行查詢模糊查詢
find_element_by_name 根據name屬性來進行查詢
find_element_by_class_name 根據class屬性來進行查詢
find_element_by_css_selector 根據css語法來進行查找
  • 多個節點
    • 注意 : 多節點在這個方法的名稱中,elment多了一個s。注意區分

Selenium可以驅動瀏覽器完成各種操作,比如填充表單、模擬點擊等。比如,我們想要完成向某個輸入框輸入文字的操作,總需要知道

from selenium import webdriver
import time

browser = webdriver.Chrome()
url = 'https://www.taobao.com/'
browser.get(url)

# 根據id來進行查找 
first_input = browser.find_element_by_id('q')

# 根據css來進行查找
second_input = browser.find_element_by_css_selector('#q')

# 根據Xpath來進行查找
three_input = browser.find_element_by_xpath('//*[@id="q"]')


# 關閉瀏覽器
browser.close()

這裏我們使用3種方式獲取輸入框,分別是根據ID、CSS選擇器、XPath獲取

另外,Selenium還提供了通過方法find_element(),它需要傳入兩個參數:查找方式和By值。實際上,它就是find_element_by_id()這種方法的通過函數版本,比如 **find_element_by_id(id) ** 等價於 **find_element(By.ID)**兩者的結果是一樣。

京東

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

# 實例化對象
browser = webdriver.Chrome()

# 請求url
url = 'https://www.jd.com/'
browser.get(url)

time.sleep(3)

# 單節點查找
# 查找京東的搜索框
browser.find_element(By.ID, 'key').send_keys('Python人工智能')

# 查找點擊按鈕並進行點擊事件
browser.find_element(By.XPATH, '//*[@id="search"]/div/div[2]/button/i').click()

time.sleep(5)
# 關閉瀏覽器
browser.close()

淘寶

from selenium import webdriver
import time

browser = webdriver.Chrome()

url = 'https://www.taobao.com/'
browser.get(url)
time.sleep(5)
# 單個節點
# 查找節點採用find來進行查找
# 在輸入框輸入Python   send_keys 爲輸入內容
browser.find_element_by_css_selector('#q').send_keys('Python')

# 定位到搜索框,並進行點擊事件 click爲點擊事件
browser.find_element_by_xpath('//*[@id="J_TSearchForm"]/div[1]/button').click()

time.sleep(5)
browser.close()

4-10 Selenium節點交互

Selenium可以驅動瀏覽器來執行一些操作,也就是說可以讓瀏覽器去模擬人的行爲去執行一些操作。比較常見的操作用法有:輸入文字時用send_keys()方法,清空文字時用clear()方法,點擊按鈕用click()方法

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

browser = webdriver.Chrome()

url = 'https://www.taobao.com/'
browser.get(url)

time.sleep(2)

input = browser.find_element(By.ID, 'q')

# 輸入內容
input.send_keys('Python')

# 清空內容
input.clear()

# 強制停止兩秒
time.sleep(2)

input.send_keys('Python人工智能')

button = browser.find_element(By.XPATH, '//*[@id="J_TSearchForm"]/div[1]/button')

# 進行點擊事件
button.click()

# 強制等待
time.sleep(2)

# 關閉瀏覽器
browser.close()

4-11 Selenium動作鏈

在上面的實例中,一些交互動作都是針對某個節點執行的。比如,對於輸入框,我們就調用它的輸入文字和清空文字方法;對於按鈕,就調用它的點擊方法。其實,還有另外一些操作,它們沒有特定的執行對象,比如鼠標拖拽、鍵盤按鈕等,這些動作用另外一種方式來執行,那就是動作鏈。

  • drag_and_drop(source, target) :
    • drop :中文意思起點
    • drag : 中文意思結束
    • source : 爲要拖拽元素的起點
    • target : 爲要拖拽元素的終點
  • perform(self)
    • 該方法爲執行動作
# @Time : 2020/5/11 20:50 
# @Author : SmallJ 

from selenium import webdriver
from selenium.webdriver import ActionChains
import time

# ActionChains爲動作鏈
url = 'https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'

browser = webdriver.Chrome()

browser.get(url)

# 該請求的頁面中存在頁面嵌套所以需使用switch_to.frame
# switch_to.frame 爲頁面嵌套 根據id來取值
# 切換到頁面嵌套
browser.switch_to.frame('iframeResult')


# 元素定位
# 請拖住我   source 中文意思 源代碼
source = browser.find_element_by_css_selector('#draggable')


# 元素定位
# 請放置到這裏   target 中文意思 目標
target = browser.find_element_by_css_selector('#droppable')

time.sleep(3)

# 進行實例化動作行爲鏈
actions = ActionChains(browser)

# drag_and_drop
# source : 爲拖拽元素的起點
# target : 爲拖拽元素的終點
actions.drag_and_drop(source, target)

# perform 爲方法執行動作
actions.perform()

首先,打開網頁中的一個拖拽實例,然後依次選中要拖拽的節點和拖拽到目標節點,接着聲明ActionChains對象並將其賦值爲actions變量的drag_and_drop()方法,再調用perform()方法執行動作,此時就完成了拖拽操作。

4-12 Selenium執行JavaScript

對於某些操作,Selenium API並沒有提供。比如,下拉進度條,它可以直接模擬運行JavaScipt此時使用execute_script()方法即可實現

# @Time : 2020/5/12 0:31 
# @Author : SmallJ 

from selenium import webdriver

url = 'https://www.zhihu.com/explore'

browser = webdriver.Chrome()
browser.get(url)
browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
browser.execute_script('alert("TO Bottom")')

4-13 Selenium獲取節點信息

語法 描述
get_attribute() 獲取屬性值
get_text() 獲取文本值
get_id 獲取節點
get_location 獲取節點在頁面中的相對位置
tag_name 獲取標籤名稱
size 獲取節點大小

前面說過,通過page_source 屬性可以獲取網頁源代碼可以獲取網頁的源代碼,接着就可以使用解析庫(如正則表達式、Beautiful Souppyquery等)來提取信息

不過,既然Selenium已經提供了選擇節點的方法,返回的是WebElement類型,那麼它也有相關的方法和屬性來直接提取節點信息,如屬性、文本等。這樣的話,我們就可以不用通過解析源代碼來提取信息了。

  • 獲取屬性

我們可以使用get_attribute()方法來獲取節點的屬性,但是其前提是先選其中的這個節點。

# @Time : 2020/5/12 14:53 
# @Author : SmallJ
# ActionChains 爲動作行爲鏈

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By

browser = webdriver.Chrome()

url = 'https://www.zhihu.com/explore'

# 請求該網頁
browser.get(url)

# 查找屬性
logo = browser.find_element(By.CLASS_NAME, 'Input')
print(logo)
print(logo.get_attribute('placeholder'))

4-14 Selenium切換Frame

我們知道網頁中有一種節點叫作iframe,也就是子Frame,相當於頁面的子頁面,它的結構和外部網頁內容的結構完全一致。Selenium打開頁面後,它的默認是在父級Frame裏面的操作,而此時如果頁面中還有子Frame,它是不能獲取子Frame裏面的節點。這時就需要使用switch_to.frame()方法來切換Frame。

# @Time : 2020/5/12 15:21 
# @Author : SmallJ 

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.common.exceptions import NoSuchElementException


url = 'https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser = webdriver.Chrome()
browser.get(url)
browser.switch_to.frame('iframeResult')
try:
    logo = browser.find_element_by_class_name('logo')
except NoSuchElementException:
    print('NO LOGO')

# 退出子頁面回到父級頁面
browser.switch_to.parent_frame()
logo = browser.find_element_by_class_name('logo')

print(logo)
print(logo.text)

首先通過switch_to.frame()方法切換到子Frame裏面,然後嘗試獲取子Frame裏的logo節點(這是不能找到的)如果找不到的話,就會拋出NoSuchElementException異常,異常被捕捉之後,就會輸出NO LOGO。接下來,重新切換到父級Frame然後再次重新獲取節點。

3-15 延時等待

隱式等待

當使用隱式等待執行測試的時候,如果Selenium沒有在DOM中找到節點,將繼續等待,超出設定時間後,則拋出找不到節點的異常。換句話說,當查找節點而節點並沒有立即出現的時候,隱式等待將等待一段時間再查找DOM,默認的時間爲0秒

# @Time : 2020/5/12 16:02 
# @Author : SmallJ 

from selenium import webdriver

browser = webdriver.Chrome()
url = 'https://www.baidu.com/'

# 隱式等待
# 隱式等待的含義就是超出時間的範圍的時候就不會繼續查找,拋出異常
# time_to_wait : 爲時間
browser.implicitly_wait(10)

browser.get(url)
input = browser.find_element_by_id('wrapper_wrapper')
print(input)

顯示等待

隱式等待的效果並不是很好,因爲我們在規定了一個固定時間,而頁面的加載時間會受到網絡條件的影響

這裏還有一種更合適的顯示等待方法,它指定要查找的節點,然後指定一個最長的等待時間。如果在規定時間內加載出來了這個節點;如果到規定時間依然沒有加載出來該節點,則拋出異常。

# 顯式等待

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

browser = webdriver.Chrome()
url = 'https://www.taobao.com/'
browser.get(url)

# WebDriverWait 裏面傳遞兩個參數
# driver 引擎
# timeout 爲超時時間
wait = WebDriverWait(browser, 10)
input_data = wait.until(EC.presence_of_element_located((By.ID, 'q')))
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'btn-search')))
print(input_data, button)

  • 這裏首先引入WebDriverWait這個對象,指定最長等待時間,然後調用它的until()方法,傳入要等待條件expected_conditions。比如,這裏傳入了presence_of_element_located這個條件,代表節點出現的意思,其參數是節點的定位元組,也就是ID爲q的節點搜索。
  • 這樣可以做到的效果就是,在10秒內如果ID爲element_to_clickable,也就是可點擊,所以查找按鈕時查找CSS選擇器爲.btn-search的按鈕,如果10內它是可點擊的,也就是成功加載出來了,也就是返回這個按鈕節點。
  • 如果超過10秒還不可以點擊,就拋出異常。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章