Python+Selenium+ChromeDriver之瀏覽器爬蟲入門

爬蟲簡介

應用場景

搜索引擎;
網站遷移;
數據整理、分析、統計;
跨域、第三方API調用;
還有,嗯釣魚網站啊;
......css

CURL

curl是利用URL語法在命令行方式下工做的開源文件傳輸工具。它被普遍應用在Unix、多種Linux發行版中,而且有DOS和Win3二、Win64下的移植版本
Shell:html

curl https://www.segmentfault.com

傳統CURL式爬蟲過程

  1. 模擬瀏覽器請求-
    編程語言內置對象或方法模擬設置cookie,User-Agent,Request Method,Query String甚至跟蹤redirect,向服務器發送一個請求
  2. 接收、處理數據流-
    對服務器響應數據流字符進行解析,或模擬HTML格式轉換爲程序相應數據類型方便操做
  3. 保存數據-
    對數據分析後本地持久化存儲(CSV,txt,jpg/png,.json文件,DB)

各語言的CURL實現:

PHP:curl_init();
Java:URLConnection;
Python:requests模塊;
Node:http模塊;
...python

CURL式爬蟲缺點:

沒法獲取由Js腳本動態生成的網頁信息-
當今Web技術的大環境下,爲了網站的性能、可擴展性、用戶友好等方向,幾乎全部的Web頁面都在使用瀏覽器腳本動態生成內容,因此若是沒有腳本執行環境就沒有數據。git

Headless瀏覽器實現頁面解析

什麼是Headless browser?

無頭瀏覽器相似於在流行的Web瀏覽器的環境中提供對網頁的自動控制,但經過命令行接口或使用網絡通訊來執行。它們特別適用於測試網頁,由於它們可以以瀏覽器相同的方式呈現和解釋HTML,包括頁面佈局、顏色、字體選擇和JavaScript和Ajax的執行等樣式元素,當使用其它測試方法時,這些元素一般是不可用的
引自Wikipedia Headless browser
簡單來講就是用瀏覽器來對目標URL進行HTML解析,CSS渲染,Js執行,藉由API甚至能夠模擬用戶行爲(鼠標點擊,鍵盤輸入),但不提供UI渲染。github

經過以上咱們能夠知道Headless browser就是咱們想要的爬蟲方式了,本文旨在探討網頁爬蟲故不對其它用途特性作過多說明。web

經常使用Headless browser

Phantomjs(項目暫封存,慎用);
Chrome
FireFoxajax

環境

Python + Selenium + ChromeDriverchrome

解釋

Python

語法簡單,有各類成熟擴展庫,爬蟲周邊的庫能夠輕易找到shell

Selenium

Selenium-主要是爲了自動化測試Web應用程序,但不侷限於此-
一句話解釋:控制瀏覽器,作任何想作的事情。(鼠標點擊、拖拽;用戶輸入,表單填充;History and Location API;Cookie;彈出對話框;定位和操做UI元素,執行JavaScript腳本)所以獲取經過ajax渲染的頁面的數據就不是什麼難事了:)
Documentation編程

ChromeDriver

如上所述,Selenium能夠操做瀏覽器,可是須要藉助ChromeDriver它是實現 WebDriver 有線協議的一個開源工具,它提供了導航到網頁、用戶輸入、JavaScript執行等等的能力。ChromeDriver經過chrome的自動代理框架控制瀏覽器

安裝

  1. 安裝 Python -
    下載並配置好環境變量,shell輸入:python -V 出現對應版本號即安裝成功!
  2. 安裝pip(Python包管理工具)-
    python默認自帶 pip 在安裝目錄的scripts目錄下,自行配置至環境變量便可,配置好後shell輸入:pip -V 出現對應版本號即安裝成功!
  3. 安裝selenium-
    shell輸入:pip install selenium 提示:Successfully installed selenium-即安裝成功!
  4. 安裝ChromeDriver-
    下載ChromeDriver,注意版本需與瀏覽器版本對應,附:版本號對應描述(64位瀏覽器下載32位便可),下載後與chrome安裝目錄放在一塊兒,而後配置至環境變量便可,配置好後shell輸入:chromedriver 無錯誤即安裝成功!
  5. 安裝python IDE pyCharm

使用

如下將經過兩個小例子來了解Selenium :)

百度搜索關鍵字「Python」

1. 實例化Driver並獲取頁面

文件名:searchPython.py

from selenium import webdriver # 從selenium導入webdriver

driver = webdriver.Chrome()  # Optional argument, if not specified will search path.
driver.get('https://www.baidu.com') # 獲取百度頁面

Shell:

py searchPython.py

chromeDriver屬性及方法
顯示以下:
百度頁面

2. 獲取輸入框元素:

input = driver.find_element_by_id('kw') #獲取輸入框
searchButton = driver.find_element_by_id('su') #獲取搜索按鈕

經常使用查找元素方法:

  1. find_element_by_id # ID
  2. find_elements_by_class_name # class
  3. find_elements_by_tag_name # 標籤名
  4. find_elements_by_name # name
  5. find_elements_by_link_text # a標籤中的text查找(精確匹配)
  6. find_elements_by_partial_link_text #a標籤中的text查找(部分匹配便可)
  7. find_elements_by_css_selector # css選擇器查找
  8. find_elements_by_xpath # find_elements_by_xpath("//input"),請翻閱文檔

查看經常使用定位元素方法
注:find_element_by_ 將獲取 find_elements_by_ 的第一個元素,獲取到的元素會被包裝爲 WebElement 對象
以上定位元素方法還能夠經過以下方式實現:

from selenium.webdriver.common.by import By #支持的定位器策略集
driver.find_element(By.ID,'kw')
driver.find_element(By.ID,'su')
'''註釋
策略集以下:
CLASS_NAME = 'class name'
CSS_SELECTOR = 'css selector'
ID = 'id'
LINK_TEXT = 'link text'
NAME = 'name'
PARTIAL_LINK_TEXT = 'partial link text'
TAG_NAME = 'tag name'
XPATH = 'xpath'
'''

3. 輸入並點擊

inputElement.send_keys("Python") #輸入框輸入"Python"
searchButton.click() #搜索

WebElement屬性及事件API
顯示以下:
百度搜索Python

完整代碼

from selenium import webdriver # 從selenium導入webdriver

driver = webdriver.Chrome()  # Optional argument, if not specified will search path.
driver.get('https://www.baidu.com') # 獲取百度頁面
inputElement = driver.find_element_by_id('kw') #獲取輸入框
searchButton = driver.find_element_by_id('su') #獲取搜索按鈕

inputElement.send_keys("Python") #輸入框輸入"Python"
searchButton.click() #搜索

獲取 bilibili 網站js動態生成的某欄目標題

這裏涉及兩個概念:
顯式等待(Explicit Waits)-
在給定的條件函數返回True以前,設置一個最長等待時間,和重複執行給定條件函數的間隔時間,若是條件函數在規定時間內返回True則即刻繼續執行,不然將拋出一個異常!
隱式等待(Implicit Waits)
告訴WebDriver在試圖找到一個元素或元素時,若是它們沒有當即可用,則會在必定時間內對DOM進行輪詢,默認設置爲0,一旦設置,就爲WebDevor對象實例的生命週期設置隱式等待。

Explicit Waits

文件名:bilibili.py

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait # 用於實例化一個Driver的顯式等待
from selenium.webdriver.common.by import By # 內置定位器策略集
from selenium.webdriver.support import expected_conditions as EC # 內置預期條件函數,具體API請參考此小節後API連接

driver = webdriver.Chrome()
driver.get('https://www.bilibili.com/v/game/esports/?spm_id_from=333.334.primary_menu.35#/9222')
try:
    WebDriverWait(driver, 20, 0.5).until(EC.presence_of_all_elements_located((By.CLASS_NAME,'vd-list'))) #使用expected_conditions自帶驗證函數
    for doctorName in driver.find_elements_by_css_selector('.vd-list li'):
        print(doctorName.find_element_by_css_selector('.r > a').text)
finally:
    driver.close() # close the driver

WebDriverWait

構造器,接受一個Driver實例,超時時長(秒),執行條件函數的間隔時間。用於實例化一個Driver的顯式等待
方法:
1.until(method, message='')

調用第一個參數給定的函數,直到函數不返回False,除了能夠接受expected_conditions內置預期條件函數還能夠自定義函數,以下

例:

def hasDoctors(d): # 自定義條件函數 when the function is called , the first prms will be a driver
if (len(d.find_elements_by_css_selector('.vd-list li'))):
    return True
return False
WebDriverWait(driver, 20, 0.5).until(hasDoctors) # 自定義函數形式

2.until_not(method, message='')

與until相反

expected_conditions

支持的內置的預期條件,簡稱EC,以下:
title_is:判斷當前頁面的title是否徹底等於(==)預期字符串
title_contains:判斷當前頁面的title是否包含預期字符串
presence_of_element_located:判斷某個元素是否被加到了dom樹裏,並不表明該元素必定可見
visibility_of_element_located:判斷某個元素是否可見,可見表明元素非隱藏,而且元素的寬和高都不等於0
visibility_of:與上述的方法同樣,區別是上述方法要傳入元祖locator即(By.ID,'kw'),此方法直接傳定位到的WebElement
presence_of_all_elements_located:判斷是否至少有1個元素存在於dom樹中,有則返回WebElements列表
text_to_be_present_in_element:判斷元素的text是否包含預期字符串
text_to_be_present_in_element_value:判斷元素的value屬性是否包含預期字符串
frame_to_be_available_and_switch_to_it:檢查給定幀是否可切換到,若是能夠,則將給定的驅動器切換到指定的iframe
......
這裏包含了全部的預置條件說明

運行Shell以下:
clipboard.png

相關文章
相關標籤/搜索