Python開發爬蟲之動態網頁抓取篇:爬取博客評論數據——通過Selenium模擬瀏覽器抓取


區別於上篇動態網頁抓取,這里介紹另一種方法,即使用瀏覽器渲染引擎。直接用瀏覽器在顯示網頁時解析 HTML、應用 CSS 樣式並執行 JavaScript 的語句。

這個方法在爬蟲過程中會打開一個瀏覽器加載該網頁,自動操作瀏覽器瀏覽各個網頁,順便把數據抓下來。用一句簡單而通俗的話說,就是使用瀏覽器渲染方法將爬取動態網頁變成爬取靜態網頁。

我們可以用 Python 的 Selenium 庫模擬瀏覽器完成抓取。Selenium 是一個用於Web 應用程序測試的工具。Selenium 測試直接運行在瀏覽器中,瀏覽器自動按照腳本代碼做出單擊、輸入、打開、驗證等操作,就像真正的用戶在操作一樣。

通過Selenium模擬瀏覽器抓取。最常用 的是 Firefox,因此下面的講解也以 Firefox 為例,在運行之前需要安裝 Firefox 瀏 覽器。

以爬取《Python 網絡爬蟲:從入門到實踐》一書作者的個人博客評論為例。網址:http://www.santostang.com/2017/03/02/hello-world/

在運行下列代碼時,一定要留意自己網絡是否暢通,如果網絡不好造成瀏覽器不能正常打開網頁及其評論數據,就可能造成爬取失敗。

1)找到評論的HTML代碼標簽。使用Chrome打開該文章頁面,右鍵點擊頁面,打開“檢查”選項。定位到評論數據。此處定位到的評論數據即是瀏覽器渲染后的數據位置,如圖:

 

 

2)嘗試獲取一條評論數據。在原來打開頁面的代碼數據上,我們可以使用以下代碼,獲取第一條評論數據。在下面代碼中,driver.find_element_by_css_selector是用CSS選擇器查找元素,找到class為’reply-content’的div元素;find_element_by_tag_name則是通過元素的tag去尋找,意思是找到comment中的p元素。最后,再輸出p元素中的text文本。

相關代碼1:

from selenium import webdriver
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary

caps=webdriver.DesiredCapabilities().FIREFOX
caps["marionette"]=True
binary=FirefoxBinary(r'E:\軟件安裝目錄\裝機必備軟件\Mozilla Firefox\firefox.exe') #把上述地址改成你電腦中Firefox程序的地址
driver=webdriver.Firefox(firefox_binary=binary,capabilities=caps)
driver.get("http://www.santostang.com/2017/03/02/hello-world/")
#page=driver.find_element_by_xpath(".//html")
driver.switch_to.frame(driver.find_element_by_css_selector("iframe[title='livere']"))
comment=driver.find_element_by_css_selector('div.reply-content-wrapper') #此處參數字段也可以是'div.reply-content',具體字段視具體網頁div包含關系而定
content=comment.find_element_by_tag_name('p')
print(content.text)
#driver.page_source

輸出:

在JS 里面也找不到https://api.gentie.163.com/products/ 哪位大神幫忙解答下。謝謝。

 代碼解析:

1)caps=webdriver.DesiredCapabilities().FIREFOX

由此可知,將上文代碼中的caps["marionette"]=True注釋掉,代碼依舊可以正常運行。

 

2)binary=FirefoxBinary(r'E:\軟件安裝目錄\裝機必備軟件\Mozilla Firefox\firefox.exe')

 3)driver=webdriver.Firefox(firefox_binary=binary,capabilities=caps)

 構建webdriver類。

還可以構建別的類型的webdriver類。

 

 

4)driver.get("http://www.santostang.com/2017/03/02/hello-world/")

 

5)driver.switch_to.frame(driver.find_element_by_css_selector("iframe[title='livere']"))

 6)comment=driver.find_element_by_css_selector('div.reply-content-wrapper')

7)content=comment.find_element_by_tag_name('p')

更多代碼含義和使用規則請參見官網API和Navigating:http://selenium-python.readthedocs.io/index.html

 8)關於driver.switch_to.frame(driver.find_element_by_css_selector("iframe[title='livere']"))中的框架定位及title內容。

可在代碼中加入driver.page_source,並且注釋掉driver.switch_to.frame(driver.find_element_by_css_selector("iframe[title='livere']"))。可在輸出內容中找到(若輸出雜亂,不好找出相關內容,可將其復制黏貼到文本文件中,使用Notepad++打開,該軟件有前后標簽對應顯示功能):

(此處只截取了相關內容的末尾部分)

若使用了driver.switch_to.frame(driver.find_element_by_css_selector("iframe[title='livere']")),而再使用driver.page_source進行相關輸出,則發現沒有上面的iframe標簽,證明我們已經將該框架解析完畢,可以進行相關定位獲取元素了。

 

上面我們只是獲取了一條評論,如果要獲取所有評論,使用循環獲取所有評論。

相關代碼2:

from selenium import webdriver
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary

caps=webdriver.DesiredCapabilities().FIREFOX
caps["marionette"]=True
binary=FirefoxBinary(r'E:\軟件安裝目錄\裝機必備軟件\Mozilla Firefox\firefox.exe')
driver=webdriver.Firefox(firefox_binary=binary,capabilities=caps)
driver.get("http://www.santostang.com/2017/03/02/hello-world/")
#page=driver.find_element_by_xpath(".//html")
driver.switch_to.frame(driver.find_element_by_css_selector("iframe[title='livere']"))

comments=driver.find_elements_by_css_selector('div.reply-content')
for eachcomment in comments:
    content=eachcomment.find_element_by_tag_name('p')
    print(content.text)
#driver.page_source

輸出:

在JS 里面也找不到https://api.gentie.163.com/products/ 哪位大神幫忙解答下。謝謝。
@先生姓張 原來要按照這里的操作才行。。。
在JS 里面也找不到https://api.gentie.163.com/products/ 哪位大神幫忙解答下。謝謝。
@先生姓張 這是網易雲上面的一個連接地址,那個服務器都關閉了
在JS 里面也找不到https://api.gentie.163.com/products/ 哪位大神幫忙解答下。謝謝。
測試
為什么我用代碼打開的文章只有兩條評論,本來是有46條的,有大神知道怎么回事嗎?
菜鳥一只,求學習群
lalala1
我來試一試
我來試一試
應該點JS,然后看里面的Preview或者Response,里面響應的是Ajax的內容,然后如果去爬網站的評論的話,點開js那個請求后點Headers -->在General里面拷貝 RequestURL 就可以了

注意代碼2中將代碼1中的comment=driver.find_element_by_css_selector('div.reply-content-wrapper') 改成了comments=driver.find_elements_by_css_selector('div.reply-content')

elements加了s

 

以上獲取的全部評論數據均屬於正常進入該網頁,等該網頁渲染完獲取的全部評論,並未進行點擊“查看更多”來加載目前還未渲染的評論。

下面介紹一種能夠爬取到所有評論,包括點擊完“查看更多”加載的目前還未渲染的評論。

相關代碼:

from selenium import webdriver
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
import time

caps=webdriver.DesiredCapabilities().FIREFOX
caps["marionette"]=True
binary=FirefoxBinary(r'E:\軟件安裝目錄\裝機必備軟件\Mozilla Firefox\firefox.exe')
driver=webdriver.Firefox(firefox_binary=binary,capabilities=caps)
driver.get("http://www.santostang.com/2017/03/02/hello-world/")
driver.switch_to.frame(driver.find_element_by_css_selector("iframe[title='livere']"))

time.sleep(60)
for i in range(0,10):
    try:
        load_more=driver.find_element_by_css_selector('div.more-wrapper')
        load_more.click()
    except:
        pass
    time.sleep(5)
comments=driver.find_elements_by_css_selector('div.reply-content')
    
for eachcomment in comments:
    content=eachcomment.find_element_by_tag_name('p')
    print(content.text)

代碼解析:

1)time.sleep(60)

延時60秒執行以下代碼。

2)load_more=driver.find_element_by_css_selector('div.more-wrapper')中的參數字符串

打開目標網頁,等目標網頁整體渲染完之后,右鍵評論區的“查看更多”。

3)load_more.click()

模擬點擊“查看更多”按鈕,進行完整顯示所有評論。

4)之所以在代碼中兩次使用延時函數,是因為不同網絡狀況和不同機器環境下可能在打開網頁以及點擊“查看更多”按鈕后不能馬上顯示評論,所以代碼需要等一等,等到頁面完全渲染后,再進行評論區數據的收集工作。

因此各延時函數的延時時間長短可視具體情況靈活設置。

 輸出結果:

在JS 里面也找不到https://api.gentie.163.com/products/ 哪位大神幫忙解答下。謝謝。
@先生姓張 原來要按照這里的操作才行。。。
在JS 里面也找不到https://api.gentie.163.com/products/ 哪位大神幫忙解答下。謝謝。
@先生姓張 這是網易雲上面的一個連接地址,那個服務器都關閉了
在JS 里面也找不到https://api.gentie.163.com/products/ 哪位大神幫忙解答下。謝謝。
測試
為什么我用代碼打開的文章只有兩條評論,本來是有46條的,有大神知道怎么回事嗎?
菜鳥一只,求學習群
lalala1
我來試一試
我來試一試
應該點JS,然后看里面的Preview或者Response,里面響應的是Ajax的內容,然后如果去爬網站的評論的話,點開js那個請求后點Headers -->在General里面拷貝 RequestURL 就可以了
現在死在了4.2節上,頁面評論是有的,但是XHR里沒有東西啊,這是什么情況?有解決的大神嗎?
@骨犬 JS
為何靜態網頁抓取不了?

奇怪了,我按照書上的方法來操作,XHR也是空的啊
@易君召 我的也是空的
你解決問題了嗎
@思い亦深 看JS不是XHR
XHR沒有顯示任何東西啊。奇怪。
找到原因了
caps["marionette"] = True
作者可以解釋一下這句話是干什么的嗎
@A cat named GitHub 改成 caps["marionette"] = False 可以運行。 目前還沒吃透代碼,先用着試試
我用的是 pycham IDE,按照作者的寫法寫的,怎么不行
@A cat named GitHub 找到原因了
caps["marionette"] = True
作者可以解釋一下這句話是干什么的嗎
對火狐版本有要求嗎
@花晨 我的也是提示火狐版本不匹配,你解決了嗎
@A cat named GitHub 重裝了geckodriver
改成caps["marionette"] = "Windows"
總之就好了
4.3.1 打開Hello World,代碼用的作者的,火狐地址我也設置了,為啥運行沒反應
from selenium import webdriver
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary

caps = webdriver.DesiredCapabilities().FIREFOX
caps["marionette"] = False
binary = FirefoxBinary(r'C:\Program Files\Mozilla Firefox\firefox.exe')
#把上述地址改成你電腦中Firefox程序的地址
driver = webdriver.Firefox(firefox_binary=binary, capabilities=caps)
driver.get("http://www.santostang.com/2017/03/02/hello-world/")
我是番茄
為什么刷新沒有XHR數據,評論明明加載出來了
為什么刷新沒有XHR數據,評論明明加載出來了
@萌萌噠的小嘰嘰丶 書里錯誤很多,留個qq吧
為什么刷新沒有XHR數據,評論明明加載出來了
第21條測試評論
第20條測試評論
第19條測試評論
第18條測試評論
第17條測試評論
第16條測試評論
第15條測試評論
第14條測試評論
第13條測試評論
第12條測試評論
第11條測試評論
第10條測試評論
第9條測試評論
第8條測試評論
第7條測試評論
第6條測試評論
第5條測試評論
第4條測試評論
第3條測試評論
第二條測試評論
第一條測試評論

 

 

參考書目:唐松,來自《Python 網絡爬蟲:從入門到實踐》

 參考書目作者關於本部分的介紹:http://www.santostang.com/2017/09/25/4-3-%E9%80%9A%E8%BF%87-selenium-%E6%A8%A1%E6%8B%9F%E6%B5%8F%E8%A7%88%E5%99%A8%E6%8A%93%E5%8F%96/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM