1. 程式人生 > >【Python3 爬蟲學習筆記】動態渲染頁面爬取 3 —— Selenium的使用 3

【Python3 爬蟲學習筆記】動態渲染頁面爬取 3 —— Selenium的使用 3

切換Frame

網頁中有一種節點叫作iframe,也就是子Frame,相當於頁面的子頁面,它的結構和外部頁面的結構完全一致。Selenium開啟頁面後,它預設是在父級Frame裡面操作,而此時如果頁面中海油子Frame,它是不能獲取到子Frame裡面的額節點的。這時就需要使用switch_to.frame()方法來切換Frame。示例如下:

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') 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)

控制檯的輸出如下:

No Logo
<selenium.webdriver.remote.webelement.WebElement (session="fa0f3dcd003ff492c67172682612cfb7", element="0.05007953924776598-2")>
RUNOOB.COM

這裡還是以前面演示動作鏈操作的網頁為例項,首先通過switch_to.frame()方法切換到Frame裡面,然後嘗試獲取父級Frame裡的logo節點,如果找不到的話,就會丟擲NoSuchElementException異常,異常被捕捉之後,就會輸出No Logo。接下來,重新切換回父級Frame,然後再次重新獲取節點,發現此時可以成功獲取了。
所以,當頁面中包含子Frame時,如果想獲取子Frame中的節點,需要先呼叫switch_to.frame()方法切換到對應的Frame,然後再進行操作。

延時等待

在Selenium中,get()方法會在網頁框架載入結束後結束執行,此時如果獲取page_source,可能並不是瀏覽器完全載入完成的頁面,如果某些頁面有額外的Ajax請求,我們在網頁原始碼中也不一定能成功獲取到。所以,這裡需要延時等待一定時間,確保節點已經加載出來。
這裡等待的方式有兩種:一種是隱式等待,一種是顯式等待。

隱式等待

當使用隱式等待執行測試的時候,如果Selenium沒有再DOM中找到節點,將繼續等待,超出設定時間後,則丟擲找不到節點的異常。換句話說,當查詢節點而節點並沒有立即出現的時候,隱式等待將等待一段時間再查詢DOM,預設的時間是0。示例如下:

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)

這裡使用了implicitly_wait()方法實現了隱式等待。

顯式等待

隱式等待的效果其實並沒有那麼好,因為我們只規定了一個固定時間,而頁面的載入時間會受到網路條件的影響。
顯式等待方法,指定要查詢的節點,然後指定一個最長等待時間。如果在規定時間內加載出來了這個節點,就返回查詢的節點;如果到了規定時間依然沒有加載出該節點,則丟擲超時異常。示例如下:

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()
browser.get('https://www.taobao.com/')
wait = WebDriverWait(browser, 10)
input = 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, button)

這裡首先引入WebDriverWait這個物件,指定最長等待時間,然後呼叫它的until()方法,傳入要等待條件expected_conditions。比如,這裡傳入了presence_of_element_located這個條件,代表節點出現的意思,其引數是節點的定位元組,也就是ID為q的節點搜尋框。
這樣可以做到的效果就是,在10秒內如果ID為q的節點(即搜尋框)成功加載出來,就返回該節點;如果超過10秒還沒有加載出來,就丟擲異常。
對於按鈕,可以更改一下等待條件,比如改為element_to_be_clickable,也就是可點選,所以查詢按鈕時查詢CSS選擇器為.btn-search的按鈕,如果10秒內它是可點選的,也就是成功加載出來了,就返回這個按鈕節點;如果超過10秒還不可點選,也就是沒有加載出來,就丟擲異常。
關於更多等待條件的引數及用法,可以參考官方文件:http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.support.expected_conditions。

前進和後退

平常使用瀏覽器時都有前進和後退功能,Selenium也可以完成這個操作,它使用back()方法後退,使用forward()方法前進。示例如下:

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()

這裡我們連續訪問3個頁面,然後呼叫back()方法回到第二個頁面,接下來再呼叫forward()方法又可以前進第三個頁面。

Cookies

使用Selenium,還可以方便地對Cookies進行操作,例如獲取、新增、刪除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':'www.zhihu.com', 'value':'germey'})
print(browser.get_cookies())
browser.delete_all_cookies()
print(browser.get_cookies())

首先,我們訪問了知乎。載入完成後,瀏覽器實際上已經生成Cookies了。接著,呼叫get_cookies()方法獲取所有的Cookies。然後,我們新增一個Cookies,這裡傳入一個字典,有name、domain和value等內容。接下來,再次獲取所有的Cookies。可以發現,結果就多了這一項新加的Cookie。最後,呼叫delete_all_cookies()方法刪除所有的Cookies。再重新獲取,發現結果就為空了。

[{'domain': '.zhihu.com', 'httpOnly': False, 'name': 'l_n_c', 'path': '/', 'secure': False, 'value': '1'}, {'domain': 'www.zhihu.com', 'expiry': 1540049555.999395, 'httpOnly': False, 'name': 'tgw_l7_route', 'path': '/', 'secure': False, 'value': '9553ebf607071b8b9dd310a140c349c5'}, {'domain': '.zhihu.com', 'expiry': 1540050459, 'httpOnly': False, 'name': '__utmb', 'path': '/', 'secure': False, 'value': '51854390.0.10.1540048660'}, {'domain': '.zhihu.com', 'expiry': 1634656655.999624, 'httpOnly': False, 'name': 'q_c1', 'path': '/', 'secure': False, 'value': '4a2ecf5be7aa4570a924d2f3e2452338|1540048654000|1540048654000'}]
[]

選項卡管理

在訪問網頁的時候,會開啟一個個選項卡。在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')

控制檯的輸出如下:

['CDwindow-F0E440AC76BF055E65B5D9B645DFBCE6', 'CDwindow-74443144C7DA82B70F4D5D3B1141AA8D']

首先訪問了百度,然後呼叫了execute_script()方法,這裡傳入window.open()這個JavaScript語句新開啟一個選項卡。接下來,我們想切換到該選項卡。這裡呼叫window_handles屬性獲取當前開啟的所有選項卡,返回的是選項卡的代號列表。想要切換選項卡,只需要呼叫switch_to_window()方法即可,其中引數是選項卡的代號。這裡我們將第二個選項卡代號傳入,即跳轉到第二個選項卡,接下來再第二個選項卡下開啟一個新頁面,然後切換回第一個選項卡重新呼叫switch_to_window()方法,再執行其他操作即可。

異常處理

在使用Selenium的過程中,難免會遇到一些異常,例如超時、節點未找到等錯誤,一旦出現此類錯誤,程式便不會繼續運行了。這裡我們可以使用try except語句來捕獲各種異常。
為了防止程式遇到異常而中斷,我們需要捕獲這些異常,示例如下:

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()

這裡我們使用try except來捕獲各種異常。比如,我們對find_element_by_id()查詢節點方法捕獲NoSuchElementException異常,這樣一旦出現這樣的錯誤,就進行異常處理,程式也不會中斷了。
控制檯的輸出如下:

No Element

相關推薦

Python3 爬蟲學習筆記動態渲染頁面 2

動作鏈 在互動操作中,一些互動動作都是針對某個節點執行的。比如,對於輸入框,我們就呼叫它的輸入文字和清空文字方法;對於按鈕,就呼叫它的點選方法。其實,還有另外一些操作,它們沒有特定的執行物件,比如滑鼠拖曳、鍵盤按鍵等,這些動作用另一種方式來執行,那就是動作鏈。

Python3 爬蟲學習筆記動態渲染頁面 4 —— 使用Selenium淘寶商品

並不是所有頁面都可以通過分析Ajax來完成抓取。比如,淘寶,它的整個頁面資料確實也是通過Ajax獲取的,但是這些Ajax介面引數比較複雜,可能會包含加密祕鑰等,所以如果想自己構造Ajax引數,還是比較困難的。對於這種頁面,最方便快捷的抓取方法就是通過Seleni

Python3 爬蟲學習筆記動態渲染頁面 3 —— Selenium的使用 3

切換Frame 網頁中有一種節點叫作iframe,也就是子Frame,相當於頁面的子頁面,它的結構和外部頁面的結構完全一致。Selenium開啟頁面後,它預設是在父級Frame裡面操作,而此時如果頁面中海油子Frame,它是不能獲取到子Frame裡面的額節點的。

Python3 爬蟲學習筆記解析庫的使用 5 —— Beautiful Soup 3

提取資訊 要獲取關聯元素節點的資訊,比如文字、屬性等,如下: html = """ <html> <body> <p class="story"> Once upon a time there were three little sisters

Python3 爬蟲學習筆記解析庫的使用 10 —— 使用pyquery 3

節點操作 pyquery提供了一系列方法來對節點進行動態修改,比如為某個節點新增一個class,移除某個節點等,這些操作有時候會為提取資訊帶來極大地便利。 addClass和removeClass html = ''' <div class="wrap"> <d

Python3 爬蟲學習筆記資料儲存 3 -- CSV檔案儲存

CSV,全稱為Comma-Separated Values,中文可以叫作逗號分隔符或字元分隔值,其檔案以純文字形式儲存表格資料。該檔案時一個字元序列,可以由任意數目的記錄組成,記錄間以某種換行符分隔。每條記錄由欄位組成,欄位間的分隔符是其他字元或字串,最常見的是逗號或製表符。不過所有記錄都有

Python3 爬蟲學習筆記基本庫的使用 8—— 正則表示式 1

三、正則表示式 1.例項引入 開啟開源中國提供的正則表示式測試工具 http://tool.oschina.net/regex/ ,輸入待匹配的文字,然後選擇常用的正則表示式,就可以得出相應的匹配結果。 對於URL來說,可以用下面的正則表示式匹配: [a-zA-z]+://[^\

Python3 爬蟲學習筆記基本庫的使用 7 —— 使用requests

抓取二進位制資料 前面我們抓取知乎的一個頁面,實際上它返回的是一個HTML文件。如何抓取圖片、音訊、視訊? 圖片、音訊、視訊這些檔案本質上都是由二進位制碼組成的,由於有特定的儲存格式和對應的解析方式,我們才可以看到這些形形色色的多媒體,所以要抓取它們,就要拿到它們的二進位制碼。 抓取

Python3 爬蟲學習筆記基本庫的使用 12—— 正則表示式 5

6. compile() compile()方法可以將正則字串編譯成正則表示式物件,以便在後面的匹配中複用。示例程式碼如下: import re content1 = '2016-12-15 12:00' content2 = '2016-12-17 12:55' content3

Python3 爬蟲學習筆記基本庫的使用 11—— 正則表示式 4

4. findall() search()方法可以返回匹配正則表示式的第一個內容,但是如果想要獲取匹配正則表示式的所有內容,就要藉助findall()方法了。該方法會搜尋整個字串,然後返回匹配正則表示式的所有內容。 上一節中的HTML文字中,如果想要獲得所有a節點的超連結、歌手和歌名,就

Python3 爬蟲學習筆記基本庫的使用 10—— 正則表示式 3

3.search() mathch()方法是從字串的開頭開始匹配的,一旦開頭不匹配,那麼整個匹配就失敗了。因為match()方法在使用時需要考慮到開頭的內容,這在匹配時並不方便。它更適合用來檢測某個字串是否符合某個正則表示式的規則。 search()方法在匹配時會掃描整個字串,然後返回第

Python3 爬蟲學習筆記基本庫的使用 9—— 正則表示式 2

1.1 匹配目標 如果想從字串中提取出一部分內容,可以用()括號將想提取的子字串括起來。()實際上標記了一個子表示式的開始和結束位置,被標記的每個子表示式會一次對應一個分組,呼叫group()方法傳入分組的索引即可獲取提取的結果。示例如下: import re content =

Python3 爬蟲學習筆記解析庫的使用 3 —— Beautiful Soup 1

Beautiful Soup可以藉助網頁的結構和屬性等特性來解析網頁。有了Beautiful Soup,我們不用再去寫一些複雜的正則表示式,只需要簡單的幾條語句,就可以完成網頁中某個元素的提取。 Beautiful Soup是Python的一個HTML或XML的解析庫,可以用它來方便地從

Python3 爬蟲學習筆記解析庫的使用 2 —— 使用XPath 2

8. 文字獲取 我們使用XPath中的text()方法獲取節點中文字,接下來嘗試獲取前面li節點中的文字,相關程式碼如下: from lxml import etree html = etree.parse('./test.html', etree.HTMLParser()) re

Python3 爬蟲學習筆記解析庫的使用 1 —— 使用XPath 1

XPath,全稱XML Path Language,即XML路徑語言,它是一門在XML文件中查詢資訊的於洋。它最初是用來搜尋XML文件的,但它同樣適用於HTML文件的搜尋。 1. XPath概覽 XPath的選擇功能十分強大,它提供了非常簡潔明瞭的路徑選擇表示式。另外,它還提供了超過

Python3 爬蟲學習筆記基本庫的使用 13 —— 抓貓眼電影排行

四、抓取貓眼電影排行 4.1 抓取分析 需要抓取的目標站點為http://maoyan.com/board/4 ,開啟之後便可以檢視到榜單資訊,如下圖所示: 排名第一的電影是霸王別姬,頁面中顯示的有效資訊有影片名稱、主演、上映時間、上映地區、評分、圖片等資訊。 將網頁滾動到最下方,

Python3 爬蟲學習筆記解析庫的使用 7 —— Beautiful Soup 5

CSS選擇器 Beautiful Soup還提供了另外一個選擇器,那就是CSS選擇器。 使用CSS選擇器時,只需要呼叫select()方法,傳入相應的CSS選擇器即可,示例如下: html = ''' <div class="panel"> <div class="

Python3 爬蟲學習筆記解析庫的使用 4 —— Beautiful Soup 2

父節點和祖先節點 如果要獲取某個節點元素的父節點,可以呼叫parent屬性: html = """ <html> <head> <title>The Dormouse's story</title> </head> <

Python3 爬蟲學習筆記解析庫的使用 9 —— 使用pyquery 2

遍歷 pyquery的選擇結果可能是多個節點,也可能是單個節點,型別都是PyQuery型別,並沒有返回像Beautiful Soup那樣的列表。 對於單個節點來說,可以直接列印輸出,也可以直接轉成字串: from pyquery import PyQuery as pq doc =

Python3 爬蟲學習筆記解析庫的使用 8 —— 使用pyquery 1

先看示例: html = ''' <div> <ul> <li class="item-0">first item</li> <li class="item-1"><a href="link2.html">secon