国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Python3網絡爬蟲實戰---37、動態渲染頁面抓取:Selenium

zhjx922 / 2240人閱讀

摘要:不過動態渲染的頁面不止這一種。再有淘寶這種頁面,它即使是獲取的數據,但是其接口含有很多加密參數,我們難以直接找出其規律,也很難直接分析來抓取。我們用一個實例來感受一下在這里們依然是先打開知乎頁面,然后獲取提問按鈕這個節點,再將其

上一篇文章:Python3網絡爬蟲實戰---36、分析Ajax爬取今日頭條街拍美圖
下一篇文章:Python3網絡爬蟲實戰---38、動態渲染頁面抓取:Splash的使用

在前面一章我們了解了 Ajax 的分析和抓取方式,這種頁面其實也是 JavaScript 動態渲染的頁面的一種情形,通過直接分析 Ajax 我們仍然可以借助于 Requests 或 Urllib 來實現數據的抓取。

不過 JavaScript 動態渲染的頁面不止 Ajax 這一種。比如中國青年網:http://news.youth.cn/gn/,它的分頁部分是由 JavaScript 生成的,并非原始 HTML 代碼,這其中并不包含 Ajax 請求。如 ECharts 的官方實例:http://echarts.baidu.com/demo...,其圖形都是經過 JavaScript 計算之后生成的。再有淘寶這種頁面,它即使是 Ajax 獲取的數據,但是其 Ajax 接口含有很多加密參數,我們難以直接找出其規律,也很難直接分析 Ajax 來抓取。

但是數據總歸是要抓取的,為了解決這些問題,我們可以直接使用模擬瀏覽器運行的方式來實現,這樣我們就可以做到瀏覽器看到是什么樣,抓取的源碼就是什么樣,也就是可見即可爬。這樣我們就不用再去管網頁內部的 JavaScript 用了什么算法渲染頁面,不用管網頁后臺的 Ajax 接口到底有哪些參數,利用模擬瀏覽器的方式我們都可以直接獲取 JavaScript 渲染的最終結果,只要能在瀏覽器中看到,我們都能抓取。

在 Python 中提供了許多模擬瀏覽器運行的庫,如 Selenium、Splash、PyV8、Ghost 等等,本章我們介紹一下其中 Selenium 和 Splash 的用法,有了它們,我們就不用再為動態渲染的頁面發愁了。

Selenium的使用

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

1. 準備工作

本節以 Chrome 為例來講解 Selenium 的用法,在本節開始之前請確保已經正確安裝好了 Chrome 瀏覽器并配置好了 ChromeDriver,另外還需要正確安裝好 Python 的 Selenium 庫,詳細的過程可以參考第一章的安裝和配置說明。

2. 基本使用

準備工作做好之后,首先我們來大體看一下 Selenium 有一些怎樣的功能,先用一段實例代碼來感受一下:

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

運行代碼之后可以發現會自動彈出一個 Chrome 瀏覽器,瀏覽器首先會跳轉到百度,然后在搜索框中輸入 Python 進行搜索,然后跳轉到搜索結果頁,等待搜索結果加載出來之后,控制臺分別會輸出當前的 URL,當前的 Cookies 還有網頁源代碼,如圖 7-1 所示:

圖 7-1 運行結果
在jon g zhi tai可以看到我們得到的當前的 URL、Cookies、源代碼都是瀏覽器中的真實內容。
所以說,如果我們用 Selenium 來驅動瀏覽器加載網頁的話,我們就可以直接拿到 JavaScript 渲染的結果了,不管是什么加密統統不用再需要擔心。
下面我們來詳細了解一下Selenium的用法。

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

這樣我們就完成了瀏覽器對象的初始化并賦值為 browser 對象,接下來我們要做的就是調用 browser 對象,讓其執行各個動作,就可以模擬瀏覽器操作了。

3. 訪問頁面

我們可以用 get() 方法來請求一個網頁,參數傳入鏈接 URL 即可,比如在這里我們用 get() 方法訪問淘寶,然后打印出源代碼,代碼如下:

from selenium import webdriver

browser = webdriver.Chrome()
browser.get("https://www.taobao.com")
print(browser.page_source)
browser.close()

運行之后我們便發現彈出了 Chrome 瀏覽器,自動訪問了淘寶,然后控制臺輸出了淘寶頁面的源代碼,隨后瀏覽器關閉。
通過這幾行簡單的代碼我們便可以實現瀏覽器的驅動并獲取網頁源碼,非常便捷。

4. 查找節點

Selenium 可以驅動瀏覽器完成各種操作,比如填充表單、模擬點擊等等,比如我們想要完成向某個輸入框輸入文字的操作,總得需要知道這個輸入框在哪里吧?所以 Selenium 提供了一系列查找節點的方法,我們可以用這些方法來獲取想要的節點,以便于下一步執行一些動作或者提取信息。

單個節點

比如我們想要從淘寶頁面中提取搜索框這個節點,首先觀察它的源代碼,如圖 7-2 所示:

圖 7-2 源代碼
可以發現它的 ID 是 q,Name 也是 q,還有許多其他屬性,那我們獲取它的方式就有多種形式了,比如find_element_by_name() 是根據 Name 值獲取,ind_element_by_id() 是根據 ID 獲取,另外還有根據XPath、CSS Selector 等獲取的方式。
我們用代碼實現一下:

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("http://*[@id="q"]")
print(input_first, input_second, input_third)
browser.close()

在這里我們使用了三種方式獲取輸入框,根據 ID、CSS Selector 和 XPath 獲取,它們返回的結果是完全一致的。
運行結果:




可以看到三個節點都是 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

另外 Selenium 還提供了通用的 find_element() 方法,它需要傳入兩個參數,一個是查找的方式 By,另一個就是值,實際上它就是 find_element_by_id() 這種方法的通用函數版本,比如 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_element() 方法,但如果有多個節點,再用 find_element() 方法查找就只能得到第一個節點了,如果要查找所有滿足條件的節點,那就需要用 find_elements() 這樣的方法,方法名稱中 element 多了一個 s ,注意區分。
比如我們在這里查找淘寶左側導航條的所有條目,如圖 7-3 所示:

圖 7-3 導航欄
就可以這樣來實現:

from selenium import webdriver

browser = webdriver.Chrome()
browser.get("https://www.taobao.com")
lis = browser.find_elements_by_css_selector(".service-bd li")
print(lis)
browser.close()

運行結果:

[, , ···]

在此簡化了一下輸出結果,中間部分省略。
可以看到得到的內容就變成了列表類型,列表的每個節點都是 WebElement 類型。
也就是說,如果我們用 find_element() 方法,只能獲取匹配的第一個節點,結果是 WebElement 類型,如果用 find_elements() 方法,則結果是列表類型,列表的每個節點是 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

當然我們和剛才一樣,也可可以直接 find_elements() 方法來選擇,所以也可以這樣來寫:

lis = browser.find_elements(By.CSS_SELECTOR, ".service-bd li")

結果是完全一致的。

5. 節點交互

Selenium 可以驅動瀏覽器來執行一些操作,也就是說我們可以讓瀏覽器模擬執行一些動作,比較常見的用法有:
輸入文字用 send_keys() 方法,清空文字用 clear() 方法,另外還有按鈕點擊,用 click() 方法。
我們用一個實例來感受一下:

from selenium import webdriver
import time

browser = webdriver.Chrome()
browser.get("https://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()

在這里我們首先驅動瀏覽器打開淘寶,然后用 find_element_by_id() 方法獲取輸入框,然后用 send_keys() 方法輸入 iPhone 文字,等待一秒之后用 clear() 方法清空輸入框,再次調用 send_keys() 方法輸入 iPad 文字,之后再用 find_element_by_class_name() 方法獲取搜索按鈕,最后調用 click() 方法完成搜索動作。
通過上面的方法我們就完成了一些常見節點的動作操作,更多的操作可以參見官方文檔的交互動作介紹:http://selenium-python.readth...。

6. 動作鏈

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

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() 方法執行動作,就完成了拖拽操作,如圖 7-4 和 7-5 所示:

圖 7-4 拖拽前頁面

圖 7-5 拖拽后頁面
以上兩圖分別為在拖拽前和拖拽后的結果。
更多的動作鏈操作可以參考官方文檔的動作鏈介紹:http://selenium-python.readth...。

7. 執行JavaScript

對于某些操作,Selenium API 是沒有提供的,如下拉進度條等,可以直接模擬運行 JavaScript,使用 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 提示框。
所以說有了這個,基本上 API 沒有提供的所有的功能都可以用執行 JavaScript 的方式來實現了。

8. 獲取節點信息

我們在前面說過通過 page_source 屬性可以獲取網頁的源代碼,獲取源代碼之后就可以使用解析庫如正則、BeautifulSoup、PyQuery 等來提取信息了。
不過既然 Selenium 已經提供了選擇節點的方法,返回的是WebElement 類型,那么它也有相關的方法和屬性來直接提取節點信息,如屬性、文本等等。這樣的話我們就可以不用通過解析源代碼來提取信息了,非常方便。
那接下來我們就看一下可以通過怎樣的方式來獲取節點信息吧。

獲取屬性

我們可以使用 get_attribute() 方法來獲取節點的屬性,那么這個的前提就是先選中這個節點。
我們用一個實例來感受一下:

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

運行之后程序便會驅動瀏覽器打開知乎的頁面,然后獲取知乎的 LOGO 節點,然后將它的 class 打印出來。
控制臺輸出結果:


zu-top-link-logo

我們通過 get_attribute() 方法,然后傳入想要獲取的屬性名,就可以得到它的值了。

獲取文本值

每個 WebEelement 節點都有 text 屬性,我們可以通過直接調用這個屬性就可以得到節點內部的文本信息了,就相當于 BeautifulSoup 的 get_text() 方法、PyQuery 的 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、位置、標簽名、大小

另外 WebElement 節點還有一些其他的屬性,比如 id 屬性可以獲取節點 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)

在這里我們首先獲得了提問按鈕這個節點,然后調用其 id、location、tag_name、size 屬性即可獲取對應的屬性值。

9. 切換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

RUNOOB.COM

我們還是以上文演示動作鏈操作的網頁為實例,首先我們通過 switch_to.frame() 方法切換到子 Frame 里面,然后我們嘗試獲取父級 Frame 里的 LOGO 節點,是不能找到的,找不到的話就會拋出 NoSuchElementException 異常,異常被捕捉之后就會輸出 NO LOGO,接下來我們重新切換回父Frame,然后再次重新獲取節點,發現就可以成功獲取了。
所以,當頁面中包含子 Frame 時,如果我們想獲取子Frame 中的節點,需要先調用 switch_to.frame() 方法切換到對應的 Frame,然后再進行操作即可。

10. 延時等待

在 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 秒還不可點擊,也就是沒有加載出來,那就拋出異常。
運行代碼,在網速較佳的情況下是可以成功加載出來的。
控制臺輸出:


可以看到控制臺成功輸出了兩個節點,都是 WebElement 類型。
如果網絡有問題,10 秒內沒有成功加載,那就拋出TimeoutException,控制臺輸出如下:

TimeoutException Traceback (most recent call last)
 in ()
      7 browser.get("https://www.taobao.com/")
      8 wait = WebDriverWait(browser, 10)
----> 9 input = wait.until(EC.presence_of_element_located((By.ID, "q")))

關于等待條件,其實還有很多,比如判斷標題內容,判斷某個節點內是否出現了某文字,在這里將所有的加載條件列舉如下:

等待條件 含義
title_is 標題是某內容
title_contains 標題包含某內容
presence_of_element_located 節點加載出,傳入定位元組,如(By.ID, "p")
visibility_of_element_located 節點可見,傳入定位元組
visibility_of 可見,傳入節點對象
presence_of_all_elements_located 所有節點加載出
text_to_be_present_in_element 某個節點文本包含某文字
text_to_be_present_in_element_value 某個節點值包含某文字
frame_to_be_available_and_switch_to_it frame 加載并切換
invisibility_of_element_located 節點不可見
element_to_be_clickable 節點可點擊
staleness_of 判斷一個節點是否仍在DOM,可判斷頁面是否已經刷新
element_to_be_selected 節點可選擇,傳節點對象
element_located_to_be_selected 節點可選擇,傳入定位元組
element_selection_state_to_be 傳入節點對象以及狀態,相等返回True,否則返回False
element_located_selection_state_to_be 傳入定位元組以及狀態,相等返回True,否則返回False
alert_is_present 是否出現Alert

更多詳細的等待條件的參數及用法介紹可以參考官方文檔:http://selenium-python.readth...。

11. 前進后退

我們平常使用瀏覽器都有前進和后退功能,使用 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()

在這里我們連續訪問三個頁面,然后調用 back() 方法就可以回到第二個頁面,接下來再調用 forward() 方法又可以前進到第三個頁面。

12. 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,然后我們添加一個 Cookie,傳入一個字典,有 name、domain、value 等內容。接下來我們再次獲取所有的 Cookies,可以發現結果就多了這一項 Cookie。最后我們調用 delete_all_cookies() 方法,刪除所有的 Cookies,再重新獲取,結果就為空了。
控制臺輸出:

[{"secure": False, "value": ""NGM0ZTM5NDAwMWEyNDQwNDk5ODlkZWY3OTkxY2I0NDY=|1491604091|236e34290a6f407bfbb517888849ea509ac366d0"", "domain": ".zhihu.com", "path": "/", "httpOnly": False, "name": "l_cap_id", "expiry": 1494196091.403418}]
[{"secure": False, "value": "germey", "domain": ".www.zhihu.com", "path": "/", "httpOnly": False, "name": "name"}, {"secure": False, "value": ""NGM0ZTM5NDAwMWEyNDQwNDk5ODlkZWY3OTkxY2I0NDY=|1491604091|236e34290a6f407bfbb517888849ea509ac366d0"", "domain": ".zhihu.com", "path": "/", "httpOnly": False, "name": "l_cap_id", "expiry": 1494196091.403418}]
[]

通過以上方法來操作 Cookies 還是非常方便的。

13. 選項卡管理

我們在訪問網頁的時候會開啟一個個選項卡,那么在 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-4f58e3a7-7167-4587-bedf-9cd8c867f435", "CDwindow-6e05f076-6d77-453a-a36c-32baacc447df"]

首先我們訪問了百度,然后調用了 execute_script() 方法,傳入 window.open() 的 JavaScript 語句新開啟一個選項卡,然后接下來我們想切換到該選項卡,可以調用 window_handles 屬性獲取當前開啟的所有選項卡,返回的是選項卡的代號列表,要想切換選項卡只需要調用 switch_to_window() 方法,傳入選項卡的代號即可。在這里我們將第二個選項卡代號傳入,即跳轉到了第二個選項卡,然后接下來在第二個選項卡下打開一個新的頁面,然后切換回第一個選項卡可以重新調用 switch_to_window() 方法,再執行其他操作即可。
如此以來我們便實現了選項卡的管理。

14. 異常處理

在使用 Selenium 過程中,難免會遇到一些異常,例如超時、節點未找到等錯誤,一旦出現此類錯誤,程序便不會繼續運行了,所以異常處理在程序中是十分重要的。
在這里我們可以使用 try except 語句來捕獲各種異常。
首先我們演示一下節點未找到的異常,示例如下:

from selenium import webdriver

browser = webdriver.Chrome()
browser.get("https://www.baidu.com")
browser.find_element_by_id("hello")

在這里我們打開百度頁面,然后嘗試選擇一個并不存在的節點,這樣就會遇到異常。
運行之后控制臺輸出如下:

NoSuchElementException Traceback (most recent call last)
 in ()
      3 browser = webdriver.Chrome()
      4 browser.get("https://www.baidu.com")
----> 5 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()

如上例所示,這里我們使用 try except 來捕獲各類異常,比如我們對 find_element_by_id() 查找節點的方法捕獲 NoSuchElementException 異常,這樣一旦出現這樣的錯誤,就進行異常處理,程序也不會中斷了。
控制臺輸出:
No Element
更多的異常累可以參考官方文檔:http://selenium-python.readth...,如果出現了某個異常,我們對它進行捕獲即可。

15. 結語

到此我們就基本對 Selenium 的常用用法有了大體的了解,有了 Selenium,處理 JavaScript 不再是難事。

上一篇文章:Python3網絡爬蟲實戰---36、分析Ajax爬取今日頭條街拍美圖
下一篇文章:Python3網絡爬蟲實戰---38、動態渲染頁面抓取:Splash的使用

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/44108.html

相關文章

  • Python3網絡爬蟲實戰---36、分析Ajax爬取今日頭條街拍美圖

    摘要:上一篇文章網絡爬蟲實戰數據爬取下一篇文章網絡爬蟲實戰動態渲染頁面抓取本節我們以今日頭條為例來嘗試通過分析請求來抓取網頁數據的方法,我們這次要抓取的目標是今日頭條的街拍美圖,抓取完成之后將每組圖片分文件夾下載到本地保存下來。 上一篇文章:Python3網絡爬蟲實戰---35、 Ajax數據爬取下一篇文章:Python3網絡爬蟲實戰---37、動態渲染頁面抓取:Selenium 本節我們...

    Leck1e 評論0 收藏0
  • Python3網絡爬蟲實戰---1、請求庫安裝:Requests、Selenium、ChromeDr

    摘要:下一篇文章網絡爬蟲實戰請求庫安裝爬蟲可以簡單分為幾步抓取頁面分析頁面存儲數據。相關鏈接官方網站官方文檔中文文檔安裝驗證安裝進入命令行交互模式,導入一下包,如果沒有報錯,則證明安裝成功。 下一篇文章:Python3網絡爬蟲實戰---2、請求庫安裝:GeckoDriver、PhantomJS、Aiohttp 爬蟲可以簡單分為幾步:抓取頁面、分析頁面、存儲數據。 在第一步抓取頁面的過程中,...

    wawor4827 評論0 收藏0
  • 首次公開,整理12年積累的博客收藏夾,零距離展示《收藏夾吃灰》系列博客

    摘要:時間永遠都過得那么快,一晃從年注冊,到現在已經過去了年那些被我藏在收藏夾吃灰的文章,已經太多了,是時候把他們整理一下了。那是因為收藏夾太亂,橡皮擦給設置私密了,不收拾不好看呀。 ...

    Harriet666 評論0 收藏0
  • Python3網絡爬蟲實戰---17、爬蟲基本原理

    摘要:在前面我們講到了和的概念,我們向網站的服務器發送一個,返回的的便是網頁源代碼。渲染頁面有時候我們在用或抓取網頁時,得到的源代碼實際和瀏覽器中看到的是不一樣的。所以使用基本請求庫得到的結果源代碼可能跟瀏覽器中的頁面源代碼不太一樣。 上一篇文章:Python3網絡爬蟲實戰---16、Web網頁基礎下一篇文章:Python3網絡爬蟲實戰---18、Session和Cookies 爬蟲,即網...

    hellowoody 評論0 收藏0
  • Python3網絡爬蟲實戰---2、請求庫安裝:GeckoDriver、PhantomJS、Aioh

    摘要:上一篇文章網絡爬蟲實戰請求庫安裝下一篇文章網絡爬蟲實戰解析庫的安裝的安裝在上一節我們了解了的配置方法,配置完成之后我們便可以用來驅動瀏覽器來做相應網頁的抓取。上一篇文章網絡爬蟲實戰請求庫安裝下一篇文章網絡爬蟲實戰解析庫的安裝 上一篇文章:Python3網絡爬蟲實戰---1、請求庫安裝:Requests、Selenium、ChromeDriver下一篇文章:Python3網絡爬蟲實戰--...

    Cristalven 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<