Python抓取網頁動態數據——selenium webdriver的使用


文章目的
當我們使用Python爬取網頁數據時,往往用的是urllib模塊,通過調用urllib模塊的urlopen(url)方法返回網頁對象,並使用read()方法獲得url的html內容,然后使用BeautifulSoup抓取某個標簽內容,結合正則表達式過濾。但是,用urllib.urlopen(url).read()獲取的只是網頁的靜態html內容,很多動態數據(比如網站訪問人數、當前在線人數、微博的點贊數等等)是不包含在靜態html里面的,例如我要抓取這個bbs網站中點擊打開鏈接 各個板塊的當前在線人數,靜態html網頁是不包含的(不信你查看頁面源代碼試試,只有簡單的一行)。像這些動態數據更多的是由JavaScript、JQuery、PHP等語言動態生成的,因此再用抓取靜態html內容的方式就不合適了。

解決思路
我嘗試過網上所說的用瀏覽器自帶的開發者工具(一般是F12彈出相應網頁的開發者工具),查看網絡可以獲得動態數據的走向,但這需要從眾多的url中找出蛛絲馬跡,個人覺得太麻煩了。另外,用查看器查看的html內容也是包含動態數據的,但這有幾個問題:怎么實時獲取查看器的html內容?怎么將查看器的html導入python程序?因此利用查看器的html內容的方法也是不符合抓取程序要求的。
而偶然間發現了selenium模塊,發現這個模塊可以很方便地根據url加載頁面獲得session,並找到當前session的相應標簽。本文將通過selenium webdriver模塊的使用,以獲取這些動態生成的內容,尤其是一些重要的動態數據。其實selenium模塊的功能不是僅僅限於抓取網頁,它是網絡自動化測試的常用模塊,在Ruby、Java里面都有廣泛使用,Python里面雖然使用相對較少,但也是一個非常簡潔高效容易上手的自動化測試模塊。通過利用selenium的子模塊webdriver的使用,解決抓取動態數據的問題,還可以可以對selenium有基本認識,為進一步學習自動化測試打下基礎。

實現過程
運行環境
我是在windows 7系統上安裝了Python 2.7版本,使用Python(X,Y)這個IDE,安裝好的Python庫沒有自帶selenium,在Python程序中直接import selenium會提示沒有這個模塊,聯網狀態下cmd直接輸入pip install selenium,系統會找到Python的安裝目錄直接下載解壓並安裝這個模塊。等到終端提示完成后可以看看,在C:\Python27\Lib\site-packages目錄下有沒有selenium模塊,這個目錄取決於你安裝Python的路徑。如果有selenium和selenium-2.47.3.dist-info這兩個文件夾,代表模塊可以在Python程序中被加載了。

使用webdriver抓取動態數據
1.先導入webdriver子模塊

from selenium import webdriver

2.獲得瀏覽器的session,瀏覽器用Firefox、Chrome、IE等都可以,這里以Firefox為例

browser = webdriver.Firefox()

3.加載頁面,url自己指定一個合法的字符串即可

browser.get(url)

4.獲得了session對象后,要定位元素,webdriver提供了一系列的元素定位方法,常用的有以下幾種方式:
id
name
class-name

link
text
partial
link
text
tag
name
xpath
cssselector

比如通過id定位,返回所有元素組成的list,lis=borwser.find_elements_by_id_name('kw'')

通過class-name定位,lis=find_elements_by_class_name('title_1')

更詳細的定位方式可以參考‘博客園-蟲師’這個大神的selenium webdriver(python)教程的第三章-定位方式部分(第一版可在百度文庫閱覽,第二版開始就收費了>-<)

5.結合正則表達式過濾相關信息

定位后的元素有些是不想要的,用正則過濾掉即可,比如我想只提取英文字符(包括0-9),建立下面的正則

pa=re.compile(r'\w+')

for u in lis:

en=pa.findall(u.lis)

print en
6.關閉會話

當執行完抓取操作后,必須關閉session,不然讓它一直占內存會影響機器其他進程的運行

browser.close()或者browser.quit()都可以關閉session,前者只是關閉當前的session,瀏覽器的webdriver不關閉,后者則是包括webdriver這些東西全部shut down

7.加入異常處理

這是有必要的,因為有時會獲得session失敗,因此要把上述語句塊放入try里面,然后exception處理異常

except NoSuchElementException:

assert 0, "can't find element"
代碼實現
我抓取了點擊打開鏈接 指定分區中各個板塊的在線人數,指定分區id號(0-9),可以獲得板塊名稱和對應的在線人數,形成列表打印出來,代碼如下

-- coding: utf-8 --
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
import time
import re

def find_sec(secid):
pa=re.compile(r'\w+')
browser = webdriver.Firefox() # Get local session of firefox
browser.get("http://bbs.byr.cn/#!section/%s "%secid) # Load page
time.sleep(1) # Let the page load
result=[]
try:

獲得版面名稱和在線人數,形成列表

board=browser.find_elements_by_class_name('title_1')
ol_num=browser.find_elements_by_class_name('title_4')
max_bindex=len(board)
max_oindex=len(ol_num)
assert max_bindex==max_oindex,'index not equivalent!'

#版面名稱有中英文,因此用正則過濾只剩英文的
for i in range(1,max_oindex):
    board_en=pa.findall(board[i].text)
    result.append([str(board_en[-1]),int(ol_num[i].text)])
    
browser.close()
return result

except NoSuchElementException:
assert 0, "can't find element"
打印分區5下面的所有板塊的當前在線人數列表
print find_sec('5')

運行結果如下:


免責聲明!

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



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