上一節中使用了分析 ajax 的方式抓取網頁,但是不是所有的動態網頁都是 ajax 生成的,有的是直接由 Javascript 生成的.
還有一些網頁可能它的 Ajax 接口有加密參數,分析其 Ajax 接口非常困難.
為了解決這些問題,我們可以使用模擬瀏覽器的方式來進行抓取,這樣,在瀏覽器中看到什麼,我們就會抓到什麼,可見即可爬,不用在管網頁內部的 Javascript 用了什麼算法渲染頁面,也不用管後來 ajax 接口有哪些參數.
Python 提供了 Selenium 庫來模擬瀏覽器的運行.
Selenium 的使用.
Selenium 是一個自動化的測試工具,利用它可以驅動瀏覽器執行特定的動作,如點擊\\下拉等操作,同時還能獲取瀏覽器當前呈現的頁面的源代碼.對於一些 Javascript 動態渲染的頁面來說,此種抓取方法非常有效.
準備工作
本節將以 Chrome 瀏覽器為例來講解 Selenium 的用法,在開始本節課程之前,請按照第一節第二節的課程安裝並配置好 Chrome 瀏覽器,ChromeDriver 驅動,Selenium 庫等.
![Python3網絡爬蟲課程 使用 selenium 爬取動態網頁](http://p2.ttnews.xyz/loading.gif)
運行代碼後,會自動彈出以惡 Chrome 瀏覽器,瀏覽器會先跳轉到百度,然後搜索 Python,接著跳轉到搜索結果頁,然後關閉.
![Python3網絡爬蟲課程 使用 selenium 爬取動態網頁](http://p2.ttnews.xyz/loading.gif)
後臺也會打印出 HTML 代碼.
瀏覽器對象
Selenium 支持多種多樣的瀏覽器如 chrome、Firefox、Internet Explorer、Microsoft Edge 等,還支持 Android 等手機瀏覽器,支持 PhantomJs、ChromeHeadless 無頭瀏覽器等。 可以使用如下方式初始化 browser 對象。
訪問頁面
瀏覽器對象初始化完成後,我們可以使用 get()方法來請求網頁,參數傳入 URL 即可。
查找結點
Selenium 可以驅動瀏覽器完成各種操作,如填充表單、模擬點擊等。
比如我們想完成在某個文本框輸入的動作,首先得定位到文本框,而 Selenium 提供了一系列查找節點的方法。
單個節點
如果我們想找到淘寶的搜索框,首先得觀察淘寶網頁的源代碼:
我們發現,這個 input 的 id 為 q,name 還是為 q。還有一些其他的屬性,比如 class 為 search-combobox-input 等,我們可以利用其這些屬性來定位這個節點。
我們使用了四種方式來定位 input 節點.
Selenium 一共提供了八種獲取單個節點的方法:
另外,Selenium 還提供了通用方法 find_element(),它需要傳入兩個參數,查找方式 By 和值。如下:
多個節點
前面介紹的方法都只能查找單個節點,如果要查找多個節點,怎麼用呢? 比如我們要查找這些節點.
我們可以這樣實現:
運行結果如下:
和上面類似, Selenium 一共提供了八種方法定位多個節點:
Selenium 也提供了通用的獲取多個節點的方法,和上面類似的 find_elements
節點交互
Selenium 可以驅動瀏覽器來執行一系列操作,如輸入文字、清空文字、點擊按鈕等。
動作鏈
Selenium 還支持鼠標拖拽、鍵盤按鍵等操作,比如我們將一個節點從某個位置拖動到另一個位置。
比如我們想拖動這個元素:
我們先打開網頁,定位到源位置和目標位置,接著聲明 ActionChains 對象,調用其方法實現拖拽操作。
執行 javascript
如果我們用到了某些 Selenium API 未提供的功能的話,應該怎麼操作呢?
比如下拉進度條,我們可以直接使用 execute_script()方法來執行 Javascript。
獲取節點信息
我們前面演示過,通過 browser 對象的 page_source 屬性可以獲取到網頁的源代碼,接著我們可以使用解析庫如 beautifulsoup、pyquery 等來解析。當然,Selenium 自身也提供了非常好用的選擇、獲取節點的方法。
獲取屬性
我們可以使用 get_attribute()方法來獲取節點的屬性,如下:
運行結果如下:
獲取文本
我們可以使用它的 text 屬性來獲取文本信息,類似於 beautifulsoup 的 get_text()方法,pyquery 的 text()方法。
運行結果如下:
獲取 id、位置、標籤名和大小
webelement 節點還有一些其他屬性,如 id、location、tag_name、size 等,如下:
運行結果如下:
切換 Frame
網頁中有一種節點叫做 iframe,就是子 frame,相當於頁面的子頁面,它的結構和外層的網頁結構是相同的。Selenium 打開頁面後,它默認實在父 frame 中操作的,如果此時頁面中還有子 frame,它是不能獲取到子 frame 中的節點的,下面就看看 Selenium 怎麼獲取子 frame 中的節點。
執行結果如下:
延時等待
Selenium 中,get()方法會在網頁加載結束後停止執行,此時如果獲取 page_source,可能獲取到的源碼並不是網頁完全加載結束後的源碼,某些節點可能在裡面找不到。如某些頁面有額外的 Ajax 請求,那麼我們就不一定能成功獲取到相關信息了。
Selenium 提供了兩種方式來解決這個問題: 一種是顯式等待,一種是隱式等待。
隱式等待
顯式等待
隱式等待只規定了一個固定的時間,而頁面的加載方式會受各方面因素的影響,所以這種方式並不好;所以我們可以用顯式等待來指定要查找的節點,然後指定一個最長的等待時間。
執行結果如下:
關於等待條件,其實很多,比如判斷標題內容、判斷是否出現了某文字等等,下面列出一些常用的等待條件。
前進和後退
我們的瀏覽器上有前進和後退按鈕,Selenium 也提供了前進和後退方法。
Cookies
Selenium 可以方便的對 Cookie 進行操作,如獲取、添加、刪除、修改等。
運行結果如下:
選項卡管理
我們使用瀏覽器的時候會打開一個個選項卡,在 Selenium 中,我們也可以對選項卡進行操作。
執行結果如下:
異常處理
在 selenium 中難免會遇到一些異常,比如節點未找到,超時等。一旦出現異常程序便不會執行了,如果我們寫個爬蟲,出現異常爬蟲就終止了,這是不行的,所以我們可以使用 try except 語句來捕獲各種異常。
閱讀更多 機器人在追你 的文章