Python抓取網(wǎng)頁(yè)動(dòng)態(tài)數(shù)據(jù)——selenium webdriver的使用

1. 文章目的

當(dāng)我們使用Python爬取網(wǎng)頁(yè)數(shù)據(jù)時(shí),往往用的是urllib模塊,通過(guò)調(diào)用urllib模塊的urlopen(url)方法返回網(wǎng)頁(yè)對(duì)象,并使用read()方法獲得url的html內(nèi)容,然后使用BeautifulSoup抓取某個(gè)標(biāo)簽內(nèi)容,結(jié)合正則表達(dá)式過(guò)濾。但是,用urllib.urlopen(url).read()獲取的只是網(wǎng)頁(yè)的靜態(tài)html內(nèi)容,很多動(dòng)態(tài)數(shù)據(jù)(比如網(wǎng)站訪問(wèn)人數(shù)、當(dāng)前在線(xiàn)人數(shù)、微博的點(diǎn)贊數(shù)等等)是不包含在靜態(tài)html里面的,例如我要抓取這個(gè)bbs網(wǎng)站中點(diǎn)擊打開(kāi)鏈接 各個(gè)板塊的當(dāng)前在線(xiàn)人數(shù),靜態(tài)html網(wǎng)頁(yè)是不包含的(不信你查看頁(yè)面源代碼試試,只有簡(jiǎn)單的一行)。像這些動(dòng)態(tài)數(shù)據(jù)更多的是由JavaScript、JQuery、PHP等語(yǔ)言動(dòng)態(tài)生成的,因此再用抓取靜態(tài)html內(nèi)容的方式就不合適了。

2. 解決思路

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

3. 實(shí)現(xiàn)過(guò)程

3.1 運(yùn)行環(huán)境

我是在windows 7系統(tǒng)上安裝了Python 2.7版本,使用Python(X,Y)這個(gè)IDE,安裝好的Python庫(kù)沒(méi)有自帶selenium,在Python程序中直接import selenium會(huì)提示沒(méi)有這個(gè)模塊,聯(lián)網(wǎng)狀態(tài)下cmd直接輸入pip install selenium,系統(tǒng)會(huì)找到Python的安裝目錄直接下載解壓并安裝這個(gè)模塊。等到終端提示完成后可以看看,在C:\Python27\Lib\site-packages目錄下有沒(méi)有selenium模塊,這個(gè)目錄取決于你安裝Python的路徑。如果有selenium和selenium-2.47.3.dist-info這兩個(gè)文件夾,代表模塊可以在Python程序中被加載了。
使用webdriver抓取動(dòng)態(tài)數(shù)據(jù)

  1. 先導(dǎo)入webdriver子模塊
    from selenium import webdriver
  2. 獲得瀏覽器的session,瀏覽器用Firefox、Chrome、IE等都可以,這里以Firefox為例
    browser = webdriver.Firefox()
  3. 加載頁(yè)面,url自己指定一個(gè)合法的字符串即可
    browser.get(url)
  4. 獲得了session對(duì)象后,要定位元素,webdriver提供了一系列的元素定位方法,常用的有以下幾種方式:
    id
    name
    class-name
    link
    text
    partial
    link
    text
    tag
    name
    xpath
    cssselector
    比如通過(guò)id定位,返回所有元素組成的list,lis=borwser.find_elements_by_id_name('kw'')
    通過(guò)class-name定位,lis=find_elements_by_class_name('title_1')
    更詳細(xì)的定位方式可以參考selenium webdriver(python)教程的第三章-定位方式部分(第一版可在百度文庫(kù)閱覽)
  5. 結(jié)合正則表達(dá)式過(guò)濾相關(guān)信息
    定位后的元素有些是不想要的,用正則過(guò)濾掉即可,比如我想只提取英文字符(包括0-9),建立下面的正則
    pa=re.compile(r'\w+')
    for u in lis:
    en=pa.findall(u.lis)
    print en
  6. 關(guān)閉會(huì)話(huà)
    當(dāng)執(zhí)行完抓取操作后,必須關(guān)閉session,不然讓它一直占內(nèi)存會(huì)影響機(jī)器其他進(jìn)程的運(yùn)行
    browser.close()或者browser.quit()都可以關(guān)閉session,前者只是關(guān)閉當(dāng)前的session,瀏覽器的webdriver不關(guān)閉,后者則是包括webdriver這些東西全部shut down
  7. 加入異常處理
    這是有必要的,因?yàn)橛袝r(shí)會(huì)獲得session失敗,因此要把上述語(yǔ)句塊放入try里面,然后exception處理異常
    except NoSuchElementException:
    assert 0, "can't find element"

4. 代碼實(shí)現(xiàn)

我抓取了點(diǎn)擊打開(kāi)鏈接 指定分區(qū)中各個(gè)板塊的在線(xiàn)人數(shù),指定分區(qū)id號(hào)(0-9),可以獲得板塊名稱(chēng)和對(duì)應(yīng)的在線(xiàn)人數(shù),形成列表打印出來(lái),代碼如下

[python] view plain

# -*- 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:  
        #獲得版面名稱(chēng)和在線(xiàn)人數(shù),形成列表  
        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!'  
          
        #版面名稱(chēng)有中英文,因此用正則過(guò)濾只剩英文的  
        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"  
  
         
print find_sec('5')  #打印分區(qū)5下面的所有板塊的當(dāng)前在線(xiàn)人數(shù)列表 

運(yùn)行結(jié)果如下:

終端打印效果

4. 總結(jié)

無(wú)論是從代碼簡(jiǎn)潔度還是執(zhí)行效率上看,selenium都非常優(yōu)秀,用selenium webdriver抓取動(dòng)態(tài)數(shù)據(jù)非常簡(jiǎn)潔高效,進(jìn)一步地利用這個(gè)實(shí)現(xiàn)數(shù)據(jù)挖掘、機(jī)器學(xué)習(xí)等深層研究也是可以的,因此selenium+python是很值得深入學(xué)習(xí)的!如果覺(jué)得用selenium每次打開(kāi)瀏覽器很不方便,可以用phantomjs模擬一個(gè)虛擬瀏覽器出來(lái),在這里就不做贅述了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容