python基礎[12]——動態渲染頁面爬取(selenium)

動態渲染頁面爬取

JavaScript動態渲染頁面,他的分頁部分有js生成,並不是原始的HTML代碼css

如淘寶使用request只能請求到頁面大體框架,沒法拿到商品數據,或部分網站換頁時url不發生變化。html

或者使用Ajax開發的網站(現在日頭條),他的接口有不少加密處理(搜索信息後信息URL通過加密處理,很難找到規律)python

Python中提供了不少模擬瀏覽器的庫,selenium ,pyV8等,來解決動態渲染的頁面。web

selenium的使用

selenium是一個自動化測試工具,利用它能夠驅動瀏覽器執行特定的動做,如點擊、下拉等操做。同時也能夠獲取瀏覽器當前呈現的頁面渲染,作到可見便可爬。用於動態頁面爬取(通過js渲染的頁面)ajax

準備工做

以谷歌瀏覽器爲例,瞭解selenium的使用chrome

  1. 須要安裝好谷歌瀏覽器,並配置好ChromeDriverapi

  2. 先去谷歌瀏覽器看版本,下載Chromedriver:http://chromedriver.storage.googleapis.com/index.html瀏覽器

  3. 配置環境變量:將下載好的可執行文件放入python的Scripts目錄下,添加至環境變量網絡

  4. 驗證:在cmd中執行ChromeDriver,會返回版本號session

    1561100027681

安裝selecnium庫

解決安裝報錯問題:https://blog.csdn.net/ever_peng/article/details/80089095

from selenium import webdriver
brower = webdriver.Chrome()
#打開一個新的Crome頁面則環境配置成功
基本使用
from selenium import webdriver#用於打開瀏覽器
from selenium.webdriver.support.wait import WebDriverWait#用於設置等待時間
from selenium.webdriver.common.keys import Keys#用於按鍵操做
from selenium.webdriver.common.by import By#用於匹配節點
from selenium.webdriver.support import expected_conditions as EC#用於等待時判斷節點是否加載,若是沒有,繼續在規定的時間加載
#打開谷歌瀏覽器
brower = webdriver.Chrome()
try:
    #請求百度網站
    brower.get('https://www.baidu.com')
    #獲取ID屬性爲kw的節點,用於輸入要搜索的信息
    input = brower.find_element_by_id('kw')
    #在搜索框輸入python
    input.send_keys('python')
    input.send_keys(Keys.ENTER)#keys是獲取鍵盤的按鍵至關於一個回車操做
    wait = WebDriverWait(brower,10)#等待頁面加載
    #判斷頁面是否響應到id屬性爲content_left的內容
    #寫的時候是以元組形式 注意括號的個數
    wait.until(EC.presence_of_element_located((By.ID, 'content_left')))

finally:
    #關閉瀏覽器
	#brower.close()
    pass

聲明瀏覽器對象

selenium支持多種瀏覽器,如chrome Firefox 也支持無界面的瀏覽器,如PhantomJS

from selenium import webdriver
brower = webdriver.Chrome()#谷歌
brower = webdriver.Firefox ()#火狐
brower = webdriver.PhantomJS()#phantomJS
#完成瀏覽器對象的初始化並將其賦值爲brower這個對象。由此調用broweer對象,讓瀏覽器執行對應的操做。

訪問頁面

使用get()方法來請求網頁,參數傳輸連接url便可,如get方法訪問淘寶頁面,打印源代碼

from selenium import webdriver

brower = webdriver.Chrome()
brower.get('https://www.taobao.com')
#獲取響應到的網頁源碼
print(brower.page_source)

查找節點

selenium能夠驅動瀏覽器完成各類操做,如填充表格、模擬點擊等操做,如向某個輸入框輸入文本操做

單個節點

根據xpath css選擇器進行選擇

#獲取id屬性爲「q」的節點
input_1 = brower.find_element_by_id('q')
input_2 = brower.find_element_by_css_selector('#q')
input_3 = brower.find_element_by_xpath('//*[@id='q']')
print(input_1)
print(type(input_1))
#<selenium.webdriver.remote.webelement.WebElement (session="af859fdfb659b14f954adaec944bb0ef", element="0.7941017431137989-1")>
#<class 'selenium.webdriver.remote.webelement.WebElement'>
返回結果爲webElement類型

全部獲取單個節點的方法

browser.find_element_by_id
browser.find_element_by_name
browser.find_element_by_class_name
#使用class_name匹配節點時,若是該節點class屬性有多個值時,只須要用其中一個值進行匹配,多個值同時匹配則產生異常
browser.find_element_by_tag_name
browser.find_element_by_link_text
browser.find_element_by_css_selector
browser.find_element_by_xpath

此外,selenium還提供了通用方法find_element()

他須要傳入兩個參數,查找方式By和值,實際爲browser.find_element_by_id()的通用方法

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

from selenium.webdriver.common.by import By
browser.find_element(By.ID, 'q')
多個節點

要匹配多個節點時使用find_element()只能獲取到一個節點,因此此時須要find_elements()方法,兩個之間的區別爲匹配多個節點時要用elements

節點交互

selenium能夠驅動瀏覽器作一系列操做,常見的send_keys()方法,清空文字是使用clear()方法,點擊按鈕click()

練習:使用selenium請求京東,在搜索框輸入榮耀20,而後等頁面加載出內容後,睡眠3秒,再去搜索華爲p30
節點.clear() 	節點.click() 		節點.send_keys() 
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.keys import Keys
from selenium import webdriver
import time
brower = webdriver.Chrome()
try:
    brower.get('https://www.jd.com/')
    input = brower.find_element_by_id('key')
    input.send_keys('榮耀20')
    input.send_keys(Keys.ENTER)
    #按鈕操做
    #button = brower.find_element+by_class_name('button')
    wait = WebDriverWait(brower,3)#等待頁面加載
    time.sleep(3)
    print('3秒後')
    input = brower.find_element_by_id('key')
    input.clear()
    input.send_keys('榮耀P30')
    input.send_keys(Keys.ENTER) 
finally:
    pass
若是class屬性裏面有兩個值,中間用空格隔開,用class_name匹配節點的時候只須要匹配其中一個,多了是找不到的

獲取節點信息

經過page_source屬性能夠獲取網頁源代碼,接着可使用解析庫(如正則,bs4等)來提取信息。

selenium也提供了節點選擇方法,返回webElement類型,能夠經過一些方法提取節點屬性、文本等。

獲取屬性

可使用get_attribute()方法來獲取節點的屬性,前提去先選中節點。

#獲取貓眼網的圖片連接
from selenium import webdriver
brower = webdriver.Chrome()

brower.get('https://maoyan.com/board/4')
input_2 = brower.find_elements_by_xpath('//img[@class="board-img"]')#注意這裏是elements
print(type(input_2))
for i in input_2:
    print(i.get_attribute('data-src'))
獲取文本

每個web element對象都有一個text屬性,經過該屬性能夠獲取節點的文本信息

#獲取top100電影名稱
name = browser.find_elements_by_xpath( '//p[@class="name"]/a') print(len(name)) 
for i in name:    
    print(i.text)

延時等待

selenium中get()方法會在網頁框架加載結束後執行,此時若是獲取page_source獲取網頁源碼可能獲得結果不是瀏覽器徹底加載後的頁面內容。

若是一些頁面有額外的ajax請求,則在此處須要延時等待一段時間,確保信息已經加載出來。

延時等待分爲:顯式等待和隱式等待

隱式等待

使用隱式等待的時候,若是selenium沒有在DOM中找到節點將繼續等待,直到超時設定時間後拋出timeout異常,默認時間爲0,以秒爲單位。

from selenium import webdriver
brower = webdriver.Chrome()
brower.implicitly_wait(10)
brower.get('url')

獲取淘寶首頁內容,查看設置延時等待與不設置響應的內容是不是一致的

若是有延時等待,則程序在get()請求後開始在延時時給定的時間內加載數據,同時匹配網頁內容。

from selenium import webdriver 
browser = webdriver.Chrome() 
browser.implicitly_wait(20) 
browser.get('https://www.taobao .com/') 
#獲取信息 
# print(browser.page_source) 
print(len(browser.find_elements _by_xpath('//h4[@class="aall"]'))) browser.close()
顯式等待

隱式等待效果通常,由於只規定了固定的時間,而頁面加載信息時間會受到網絡條件影響

顯式等待它指定要查找的內容,而後指定時間進行等待。若是在規定時間加載到這個節 點則返回查找的節點,若是在規定時間依然沒有加載到該節點數據,則拋出異常

移動右側下拉條

#將下拉條從頂部拖拽到中間位置 
brower.execute_script('window.scrollTo(0,document.body.scrollHeight/2)')

前進和後退

使用back()昂發進行後退,使用forward()方法進行前進

from selenium import webdriver
import time
browser=webdriver.Chrome()
browser.get('https://www.baidu.com/')
browser.get('https://www.taobao.com/')
browser.get('https://www.jd.com/')

browser.back()
time.sleep(10)
browser.forward()

捕獲異常

from selenium.common.exceptions import TimeoutException
#導入異常
try : 
    pass
except TimeoutException:
    pass
finally:
    pass
相關文章
相關標籤/搜索