python3編寫網絡爬蟲14-動態渲染頁面爬取

1、動態渲染頁面爬取php

上節課咱們瞭解了Ajax分析和抓取方式,這其實也是JavaScript動態渲染頁面的一種情形,
經過直接分析Ajax,藉助requests和urllib實現數據爬取css

可是javaScript動態渲染布置Ajax一種 例如中國青年網(http://news.youth.cn/gn/)分頁部分由js生成,
並不是原始HTML代碼,這其中並不包含ajax請求 好比ECharts官方示例(http://echarts.baidu.com/demo.html#bar-negative)
圖形都是通過js計算生成的,再有淘寶 即使是ajax請求 可是接口不少都是加密參數,很難找到規律,也很難直接分析ajax抓取html

python提供了不少模擬瀏覽器運行的庫,例如Selenium Splash,PyV8 Ghost等。java


1. Selenium的使用python

selenium是一個自動化測試工具,利用它能夠驅動瀏覽器執行特定的動做,例如 點擊 下拉等操做,
同時還能夠獲取瀏覽器當前呈現的頁面的源代碼,作到可見既可爬。
對於一些js動態渲染的頁面來講,此種爬取方式很是有效jquery

1.1 安裝 web

安裝:python的Selenium庫 ajax

pip install selenium

 

驗證:python命令行 import selenium
無報錯信息表示安裝成功

安裝Google瀏覽器並配置ChromeDriverchrome

點擊Google菜單 幫助 -> 關於Google Chrome -> 查看版本號 (版本 71.0.3578.98(正式版本) (64 位)) api

下載ChromeDriver

官網地址:

https://sites.google.com/a/chromium.org/chromedriver

下載地址:

https://chromedriver.storage.googleapis.com/index.html

對比本身瀏覽器版本下載相應版本

解壓後把文件放到 python的script目錄下 例如 'C:\Users\admin\AppData\Local\Programs\Python\Python36\Scripts'

驗證: cmd命令行 執行 chromedriver 輸出以下信息:

Starting ChromeDriver 2.45.615291 (ec3682e3c9061c10f26ea9e5cdcf3c53f3f74387) on port 9515
Only local connections are allowed.

表示安裝 ChromeDriver配置好了

測試 在python程序中執行

from selenium import webdriver browser = webdriver.Chrome()

程序運行後 彈出空白的Chrome瀏覽器 說明咱們以前配置都沒有問題

沒有彈出從新配置 閃退多是版本不兼容

1.2 基本做用

示例以下:

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait browser = webdriver.Chrome() try:   browser.get('https://www.baidu.com')   input = browser.find_element_by_id('kw')   input.send_keys('Python')   input.send_keys(Keys.ENTER)   wait = WebDriverWait(browser,10)   wait.until(EC.presence_of_element_located((By.ID,'content_left')))   print(browser.current_url)   print(browser.get_cookies())   print(browser.page_source) finally:   browser.close()

能夠看到自動彈出瀏覽器 首先跳轉百度 而後搜索框輸入Python 接着跳轉搜索結果頁

搜索結果出來後 控制檯輸出當前URL Cookies 網頁源代碼

使用selenium 驅動瀏覽器加載網頁就能夠拿到js渲染結果了 不用擔憂什麼加密系統


1.3 聲明瀏覽器對象

Selenium 支持很是多的瀏覽器 例如 Chrome Firefox Edge等 還有Android BlackBerry等手機端瀏覽器
也支持PhantomJS 無界面瀏覽器

初始化方法:

from selenium import webdriver browser = webdriver.Chrome() browser = webdriver.Firefox() browser = webdriver.Edge() browser = webdriver.PhantomJS() browser = webdriver.Safari()

1.4 訪問頁面

get() 方法請求頁面 參數 傳入連接URL 例如訪問淘寶

from selenium import webdriver browser = webdriver.Chrome() browser.get('https://www.taobao.com') print(browser.page_source) browser.close()

彈出Chrome瀏覽器 自動訪問淘寶 控制檯輸出網頁源代碼隨後瀏覽器關閉


1.5 查找節點

Selenium 能夠驅動瀏覽器完成各類操做,例如填充表單,模擬點擊等
例如想要完成某個輸入框輸入文字操做 須要查找輸入框位置

單個節點:
例如淘寶頁面提取搜索框節點

id是q name是q

利用
find_element_by_name() 獲取name值
find_element_by_id() 獲取id
還能夠根據xpath CSS選擇器等獲取方式

示例以下:

from selenium import webdriver browser = webdriver.Chrome() browser.get('https://www.taobao.com') input_first = browser.find_element_by_id('q') input_second = browser.find_element_by_css_selector('#q') input_third = browser.find_element_by_xpath('//*[@id="q"]') print(input_first,input_second,input_third) browser.close()

 

返回WebElement類型

獲取單個節點的方法:

find_element_by_id() find_element_by_name() find_element_by_xpath() find_element_by_link_text() find_element_by_partial_link_text() find_element_by_tag_name() find_element_by_class_name() find_element_by_css_selector()

另外 還提供了通用方法 find_element() 須要傳入兩個參數:1.查找方式 2.值
例如:find_element(By.ID,id) 等價於 find_element_by_id(id)

示例以下:

from selenium import webdriver from selenium.webdriver.common.by import By browser = webdriver.Chrome() browser.get('https://www.taobao.com') input_first = browser.find_element(By.ID,'q') print(input_first) browser.close()

多個節點:
find_elements() 查找全部知足條件的節點

示例: 查找淘寶左側導航條的全部條目

from selenium import webdriver browser = webdriver.Chrome() browser.get('http://www.taobao.com') lis = browser.find_elements_by_css_selector('.service-bd li') print(lis) browser.close()

返回列表 每一個元素是WebElement類型

獲取多個節點的方法:

find_elements_by_id() find_elements_by_name() find_elements_by_xpath() find_elements_by_link_text() find_elements_by_partial_link_text() find_elements_by_tag_name() find_elements_by_class_name() find_elements_by_css_selector()

1.6 節點交互

send_keys() 輸入文字
clear() 清空文字
click() 點擊按鈕

示例:

from selenium import webdriver import time browser = webdriver.Chrome() browser.get('http://www.taobao.com') input = browser.find_element_by_id('q') input.send_keys('iPhone') time.sleep(1) input.clear() input.send_keys('iPad') button = browser.find_element_by_class_name('btn-search') button.click()

首先打開淘寶 獲取輸入框 輸入iphone文字 等待一秒 清空輸入框 輸入ipad 說去搜索按鈕 點擊按鈕

官方文檔交互動做 :http:selenium-python.readthedocs.io/api.html#module-selenium.webdrive.remote.webelement

1.7 動做鏈

例如鼠標拖拽 鍵盤按鍵等動做

示例:

from selenium import webdriver from selenium.webdriver import ActionChains browser = webdriver.Chrome() url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable' browser.get(url) browser.switch_to.frame('iframeResult') source = browser.find_element_by_css_selector('#draggable') target = browser.find_element_by_css_selector('#droppable') actions = ActionChains(browser) actions.drag_and_drop(source,target) actions.perform()

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

更多動做鏈操做參考官方文檔:http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.action_chains


1.8 執行JavaScript

對於某些操做selenium API 並無提供 例以下拉進度條 可使用 execute_script()方法 便可實現

示例:

from selenium import webdriver browser = webdriver.Chrome() browser.get('https://www.zhihu.com/explore') browser.execute_script('window.scrollTo(0,document.body.scrollHeight)') browser.execute_script('alert("To Bottom")')

這裏利用 execute_script()方法 將進度條下拉到最底部,而後彈出alert提示框

1.9 獲取節點信息

獲取屬性
get_attribute() 方法 獲取節點屬性 前提是選中這個節點

示例:驅動瀏覽器打開知乎頁面 獲取知乎log節點 打印出class

from selenium import webdriver from selenium.webdriver import ActionChains browser = webdriver.Chrome() url = 'https:www.zhihu.com/explore' browser.get(url) logo = browser.find_element_by_id('zh-top-link-logo') print(logo) print(logo.get_attribute('class'))

獲取文本值
text屬性

示例:打開知乎頁面 獲取「提問」按鈕的節點 將文本打印出來

from selenium import webdriver browser = webdriver.Chrome() url = 'https:www.zhihu.com/explore' browser.get(url) input = browser.find_element_by_class_name('zu-top-add-question') print(input.text)

獲取 ID 位置 標籤名和大小

id屬性能夠獲取id location屬性獲取該節點在頁面中相對位置,tag_name屬性獲取標籤名 size獲取節點大小(寬高)

示例: 得到「提問」按鈕節點 調用id location tag_name size屬性分別獲取對應的屬性值

from selenium import webdriver browser = webdriver.Chrome() url = 'https:www.zhihu.com/explore' browser.get(url) input = browser.find_element_by_class_name('zu-top-add-question') print(input.id) print(input.location) print(input.tag_name) print(input.size)

1.10 切換frame

頁面中有一種節點iframe 也就是frame 至關於當前頁面的子頁面 結構和外部網頁結構徹底一致
selenium 打開頁面默認是在父級frame裏面操做 若是裏面還子頁面是獲取不到裏面節點的
須要使用 switch_to.frame() 方法切換子frame

示例:獲取動做連接操做網頁的logo

import time from selenium import webdriver from selenium.common.exceptions import NoSuchElementException browser = webdriver.Chrome() url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable' browser.get(url) browser.switch_to.frame('iframeResult')#切換到子frame
try:   logo = browser.find_element_by_class_name('logo') except NoSuchElementException:   print('NO LOGO') browser.switch_to.parent_frame()#切換到父frame
logo = browser.find_element_by_class_name('logo') print(logo) print(logo.text)

1.11 延時等待

selenium中get方法會在網頁框架加載結束後結束執行 若是此時獲取page_source 可能並非網頁加載徹底的頁面
若是某些頁面存在ajax加載 網頁源代碼也不必定能獲取的到 因此須要延時等待必定時間,確保節點已經加載出來

兩種方式 隱式等待 顯式等待

隱式等待

當使用隱式等待時 selenium沒有在DOM中找到節點 將繼續等待 超出設置時間後 拋出異常 默認時間是0
示例: implicitly_wait() 方法

from selenium import webdriver browser = webdriver.Chrome() browser.implicitly_wait(10) browser.get('https://www.zhihu.com/explore') input = browser.find_element_by_class_name('zu-top-add-question') print(input)

顯式等待 until() 方法

若是頁面加載受網絡條件影響 隱式效果就不是很好

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait#引入 WebDriverWait對象
 browser = webdriver.Chrome() browser.get('https://www.taobao.com/') wait = WebDriverWait(browser,10) input = wait.until(EC.presence_of_element_located((By.ID,'q')))#調用until方法 節點出現
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'.btn-search')))#調用until方法 按鈕可點擊
print(input,button)

更多等待條件

title_is() 標題是某內容 title_contains() 標題包含某內容 presence_of_element_located() 節點加載出來 傳入定位元組 例如(By.ID,'P') visibility_of_element_located() 節點可見 傳入定位元組 visibility_of() 可見 傳入節點對象 presence_of_all_element_located() 全部節點加載出來 text_to_be_present_in_element() 某個節點文本包含某文字 text_to_be_present_in_element_value() 某個節點值包含某文字 frame_to_be_available_and_switch_to_it()加載並切換 invisibility_of_element_located() 節點不可見 element_to_be_clickable() 節點可點擊 staleness_of() 判斷一個節點是否仍在DOM 可判斷頁面是否刷新 element_located_to_be_selected() 節點可選擇 傳入節點對象 element_selection_state_to_be() 傳入節點對象以及狀態 相等返回True 不然False element_located_selected_to_be() 傳入定位元組以及狀態 相等返回True 不然False alert_is_present() 是否出現警告

更多參考官方文檔 http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.support.expected_conditions

1.12 前進和後退

forward() 方法前進 back()方法後退

示例:

import time from selenium import webdriver browser = webdriver.Chrome() browser.get('https://www.baidu.com') browser.get('https://www.taobao.com') browser.get('https://www.python.org') browser.back() time.sleep(1) browser.forward() browser.close()

1.13 Cookies

獲取 get_cookies()
添加 add_cookie()
刪除 delete_all_cookies()

示例:

from selenium import webdriver browser = webdriver.Chrome() browser.get('https://www.zhihu.com/explore') print(browser.get_cookies()) browser.add_cookie({'name':'name','domain':'wwww.zhihu.com','value':'germery'}) print(browser.get_cookies()) browser.delete_all_cookies() print(browser.get_cookies())

1.14 選項卡管理

在訪問網頁時會出現一個個選項卡 selenium能夠對選項卡進行操做

示例:

import time from selenium import webdriver browser = webdriver.Chrome() browser.get('https:www.baidu.com') browser.execute_script('window.open()') print(browser.window_handles) browser.switch_to_window(browser.window_handles[1]) browser.get('https://www.taobao.com') time.sleep(1) browser.switch_to_window(browser.window_handles[0]) browser.get('https://python.org')

1.15 異常處理

在使用selenium的過程當中 不免會出現一些異常 例如 超時 節點未找到 一旦出現此類錯誤程序就不會執行了
使用 try except 捕獲異常

示例:節點未找到

from selenium import webdriver browser = webdriver.Chrome() browser.get('https:www.baidu.com') browser.find_element_by_id('hello')

報錯 NoSuchElementException

防止程序遇到異常中斷 捕獲異常示例:

from selenium import webdriver from selenium.common.exceptions import TimeoutException,NoSuchElementException browser = webdriver.Chrome() try:   browser.get('https://www.baidu.com') except TimeoutException:   print('Time Out') try:   browser.find_element_by_id('hello') except NoSuchElementException:   print('No Element') finally: browser.close()

更多異常類 官網:http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.exceptions

相關文章
相關標籤/搜索