楊 健,陳 偉
(諸暨市公安局,浙江 紹興 311800)
隨著信息技術(shù)的發(fā)展,網(wǎng)絡(luò)數(shù)據(jù)成為一種重要資產(chǎn),如何快速有效地提取和分析數(shù)據(jù)是目前該研究領(lǐng)域的熱點(diǎn)[1]。夏火松等[2]、云洋[3]應(yīng)用Requests技術(shù)分別開發(fā)了商品評論、百度貼吧圖片爬蟲,優(yōu)化了爬蟲算法,并為用戶提供了有效的信息參考。劉燦等[4]、WU等[5]基于Scrapy框架開發(fā)了教育新聞、Steam商店信息爬蟲,實(shí)現(xiàn)了個性化推薦、自動獲取游戲信息。潘洪濤[6]利用Selenium技術(shù)具有的自動化測試特性,設(shè)計(jì)與實(shí)現(xiàn)了一種多源統(tǒng)一爬蟲框架,可以面向多個網(wǎng)站數(shù)據(jù)源,以統(tǒng)一的接口形式實(shí)現(xiàn)數(shù)據(jù)抓取;許景賢等[7]安裝配套的Chrome WebDriver驅(qū)動,調(diào)用Selenium接口模擬人工自動點(diǎn)擊瀏覽器,繞過淘寶配置的反爬措施,成功爬取淘寶上的商品價格和名稱。上述研究工作使用Python多種爬蟲技術(shù)實(shí)現(xiàn)了相關(guān)業(yè)務(wù)需求,但均沒有探討技術(shù)區(qū)別和選用理由。
針對以上問題,本文介紹了基于Python的Requests、Scrapy和Selenium三種主流爬蟲技術(shù),設(shè)計(jì)實(shí)現(xiàn)網(wǎng)絡(luò)爬蟲的程序框架。通過設(shè)計(jì)爬取“站長之家”網(wǎng)站簡歷數(shù)據(jù)的實(shí)驗(yàn)案例,實(shí)現(xiàn)不同技術(shù)的環(huán)境配置、程序開發(fā)和并發(fā)性能等的比較。結(jié)果表明,不同的網(wǎng)絡(luò)爬蟲技術(shù)具有不同的優(yōu)點(diǎn)和缺點(diǎn),適用不同的業(yè)務(wù)場景,因此在開發(fā)方案選擇上要合理選用,以提升數(shù)據(jù)爬取的穩(wěn)定性、準(zhǔn)確性和工作效率。
使用Requests、Scrapy和Selenium技術(shù)開發(fā)的網(wǎng)絡(luò)爬蟲,由于抓取的原始數(shù)據(jù)格式包含HTML、XML和JSON,因此對目標(biāo)數(shù)據(jù)的獲取要輔以其他技術(shù)解析并持久化保存。
Requests技術(shù)屬于爬蟲基礎(chǔ)性工具包,它模擬人輸入網(wǎng)址向服務(wù)器遞交網(wǎng)絡(luò)請求,實(shí)現(xiàn)自動爬取HTML網(wǎng)頁頁面信息的功能。根據(jù)HTTP協(xié)議對資源的六大操作方法,Requests配備對應(yīng)的GET、POST、HEAD、PUT、PATCH、DELETE六個基礎(chǔ)方法和一個REQUEST通用方法,具有HTTP連接池自動化、持久Cookie會話、SSL認(rèn)證等基本功能。
Selenium技術(shù)是一個基于Web應(yīng)用程序且支持瀏覽器驅(qū)動的開源自動化測試框架,其運(yùn)行過程就是一個可視化地模擬人輸入網(wǎng)址、滾動鼠標(biāo)、點(diǎn)擊等動態(tài)的操作過程,能夠?qū)hrome、Firefox、IE等瀏覽器中的對象元素進(jìn)行定位、窗口跳轉(zhuǎn)及結(jié)果比較等操作,具有執(zhí)行網(wǎng)頁JS加載、Ajax動態(tài)異步等技術(shù),能做到可見即可爬,支持Python、Java、C#主流編程語言二次開發(fā)。
Scrapy技術(shù)是一個網(wǎng)站數(shù)據(jù)爬取和結(jié)構(gòu)性數(shù)據(jù)提取的應(yīng)用框架,包含引擎、調(diào)度器、下載器、解析爬蟲、項(xiàng)目管道五個模塊和下載器、解析爬蟲兩個中間件。該技術(shù)框架已設(shè)計(jì)了爬蟲通用的數(shù)據(jù)和業(yè)務(wù)接口,方便根據(jù)業(yè)務(wù)需求聚焦爬取、解析、下載、存儲等操作。
網(wǎng)絡(luò)爬蟲爬取初始數(shù)據(jù)后需要進(jìn)行解析,常用的技術(shù)如下:(1)Xpath庫,它能夠?qū)μ囟〝?shù)據(jù)進(jìn)行定位,以更好地獲取特定元素,通常存儲在XML文檔中,在一定程度上起著導(dǎo)航作用。(2)RE正則表達(dá)式庫,它通過規(guī)定一系列的字符及符號來進(jìn)行數(shù)據(jù)篩選,實(shí)現(xiàn)圖片、視頻和關(guān)鍵字的搜索,進(jìn)而實(shí)現(xiàn)信息的爬取。(3)BS4庫,它運(yùn)用HTML解析策略,把HTML源代碼重新進(jìn)行格式化,方便使用者對其中的節(jié)點(diǎn)、標(biāo)簽、屬性等進(jìn)行操作,完成網(wǎng)站數(shù)據(jù)的抓取、篩選操作。(4)JSON庫,它是一種輕量級的數(shù)據(jù)交換格式,采用對象和數(shù)組的組合形式表示數(shù)據(jù),用于將數(shù)據(jù)對象編碼為JSON格式進(jìn)行輸出或存儲,再將JSON格式對象解碼為Python對象。
網(wǎng)絡(luò)爬蟲一旦啟動將采取定制、自動化模式爬取目標(biāo)網(wǎng)頁的數(shù)據(jù),首先從初始頁面的URL地址開始,通過向目標(biāo)站點(diǎn)發(fā)送一個Web請求,等待服務(wù)器響應(yīng);然后獲取響應(yīng)的頁面內(nèi)容,可能包含HTML、JSON字符串、二進(jìn)制等數(shù)據(jù)類型,根據(jù)響應(yīng)網(wǎng)頁數(shù)據(jù)類型,輔助以用正則表達(dá)式等網(wǎng)頁解析庫進(jìn)行解析,獲得目標(biāo)數(shù)據(jù);最后保存數(shù)據(jù),將數(shù)據(jù)保存為文本格式或者保存至數(shù)據(jù)庫。如果目標(biāo)數(shù)據(jù)涉及URL地址嵌套關(guān)聯(lián),就要通過分析頁面中的其他相關(guān)URL,抓取新的網(wǎng)頁鏈接,反復(fù)循環(huán),直至爬取、分析和獲取所有頁面內(nèi)容。通用網(wǎng)絡(luò)爬蟲模型如圖1所示。
圖1 通用網(wǎng)絡(luò)爬蟲模型Fig.1 General web crawler model
本實(shí)驗(yàn)使用Python 3.6.4版本作為開發(fā)環(huán)境,采用集成工具PyCharm 2020.1版本開發(fā)。爬蟲核心代碼如下:
本實(shí)驗(yàn)以“站長之家”的簡歷欄目(https://sc.chinaz.com/jianli/)作為爬取數(shù)據(jù)目標(biāo),該網(wǎng)站簡歷欄目素材豐富,網(wǎng)頁包含JS、CSS、文字、圖片、文件等,網(wǎng)站robots協(xié)議允許所有網(wǎng)絡(luò)爬蟲訪問。實(shí)驗(yàn)環(huán)境使用“聯(lián)想”的小新AIR-14 2020筆記本電腦(操作系統(tǒng):Windows 10專業(yè)版;處理器:Intel酷睿i5,CPU運(yùn)行頻率1.00 GHz;內(nèi)存16 GB)和浙江大學(xué)華家池校區(qū)Wi-Fi網(wǎng)絡(luò)SCEZJU-GUEST。
實(shí)驗(yàn)通過環(huán)境配置、代碼實(shí)現(xiàn)、單線程和多線程等維度,比較三種爬蟲技術(shù)的程序開發(fā)難易程度及耗時。為避免數(shù)據(jù)解析影響實(shí)驗(yàn)結(jié)果,在耗時計(jì)算中剔除了第三方庫解析原始數(shù)據(jù)的時間,具體步驟如下。
Step1:安裝配置。根據(jù)Requests、Scrapy和Selenium技術(shù)的安裝要求及依賴包,配置環(huán)境和第三方插件。
Step2:準(zhǔn)備工作。通過瀏覽器查看目標(biāo)網(wǎng)頁,確定URL地址及翻頁參數(shù)。
Step3:獲取數(shù)據(jù)。向目標(biāo)網(wǎng)頁發(fā)起請求,正常響應(yīng)返回得到原始數(shù)據(jù)。
Step4:解析內(nèi)容。通過Xpath庫解析獲取目標(biāo)數(shù)據(jù)并在IDEA工具中打印。
Step5:變更URL翻頁參數(shù),通過步驟1至步驟4中,分別進(jìn)行單線程、多線程等實(shí)驗(yàn)并記錄時間。
5.2.1 環(huán)境安裝、代碼開發(fā)比較
表1顯示了三種爬蟲技術(shù)的環(huán)境配置與開發(fā)實(shí)現(xiàn)對比信息。其中,Requests、Scrapy和Selenium包通過Python的pip命令安裝。在程序開發(fā)中,Requests、Scrapy網(wǎng)絡(luò)爬蟲在模擬訪問時要攜帶Headers請求頭,請求返回的響應(yīng)不會執(zhí)行獲取網(wǎng)頁中的JS動態(tài)代碼,無法得到由JS異步請求的網(wǎng)頁數(shù)據(jù)。開發(fā)Scrapy網(wǎng)絡(luò)爬蟲,程序代碼要按照框架自帶的引擎、調(diào)度器、下載器、解析爬蟲、項(xiàng)目管道等模塊要求開發(fā),如果要調(diào)用爬蟲抓取的不同數(shù)據(jù)進(jìn)行業(yè)務(wù)定制,技術(shù)實(shí)現(xiàn)不夠靈活。Selenium網(wǎng)絡(luò)爬蟲必須安裝配套的Webdriver驅(qū)動以調(diào)用本機(jī)瀏覽器,Selenium爬蟲通過本機(jī)瀏覽器模擬訪問網(wǎng)頁,因此代碼中不需要攜帶Headers請求頭。爬取網(wǎng)頁的JS動態(tài)代碼被瀏覽器執(zhí)行,獲取的響應(yīng)已包含JS異步請求數(shù)據(jù),這是Requests、Scrapy技術(shù)無法實(shí)現(xiàn)的。
表1 環(huán)境配置與開發(fā)實(shí)現(xiàn)對比表Tab.1 Comparison table of environment configuration and development implementation
5.2.2 單線程運(yùn)行下爬蟲性能分析
采用單線程爬取網(wǎng)頁實(shí)驗(yàn)中,運(yùn)行三種爬蟲程序,分別爬取目標(biāo)網(wǎng)站網(wǎng)頁數(shù)量為10 頁、100 頁、500 頁和1,000 頁且運(yùn)行3 次,記錄時間和計(jì)算平均值。表2顯示了三種爬蟲爬取頁面的耗時對比。經(jīng)分析發(fā)現(xiàn):(1)對同樣頁面數(shù)進(jìn)行輪爬,三種爬蟲第1、2、3 次的爬取耗時差異不大,但三種爬蟲之間的爬取耗時對比差異較大。(2)Requests爬蟲的四輪實(shí)驗(yàn)的平均每頁爬取時間為0.24 s、0.27 s、0.28 s和0.26 s,爬取速度比較穩(wěn)定;Selenium爬蟲的四輪實(shí)驗(yàn)的平均每頁爬取時間為1.08 s、1.47 s、1.64 s和1.42 s,當(dāng)爬取的頁面數(shù)量較多時,平均爬取每頁的耗時多于爬取少量頁面的耗時,但總體速度比較穩(wěn)定;Scrapy爬蟲的四輪實(shí)驗(yàn)的平均每頁爬取時間為0.08 s、0.02 s、0.02 s和0.02 s,爬取每頁的平均耗時均不到0.1 s,速度極快且穩(wěn)定。在單線程爬取實(shí)驗(yàn)中,Scrapy爬蟲耗時最少、Selenium爬蟲耗時最多。(3)三種爬蟲爬取網(wǎng)頁數(shù)量為10 頁、100 頁、500 頁和1,000 頁的平均耗時接近線性遞增。從增量來看,Scrapy爬蟲耗時最少,Selenium爬蟲耗時最多,隨著爬取頁面數(shù)量的增加,三種爬蟲的爬取耗時差距逐漸增大,如圖2所示。
圖2 單線程爬取平均耗時對比Fig.2 Comparison of average time consumption of single thread crawling
表2 單線程爬取耗時對比Tab.2 Single thread crawling time comparison(單位:秒/次)
5.2.3 多線程運(yùn)行下爬蟲性能分析
采用多線程爬取網(wǎng)頁實(shí)驗(yàn)中,統(tǒng)一開發(fā)并發(fā)線程數(shù)為16個,分別運(yùn)行三種爬蟲程序爬取目標(biāo)網(wǎng)站網(wǎng)頁數(shù)量1,000 頁且運(yùn)行3 次,計(jì)算耗時平均值。表3顯示為單線程和多線程爬取的比較情況。分析發(fā)現(xiàn)以下情況:(1)Requests、Selenium和Scrapy爬蟲在多線程爬取時,平均耗時分別為25.39 s、172.12 s和23.52 s,平均每頁耗時分別為0.03 s、0.17 s和0.02 s,Scrapy和Requests爬蟲耗時最少并且耗時差距接近,而Selenium爬蟲耗時依然最多。(2)Requests和Selenium爬蟲采用多線程爬取頁面時,耗時明顯少于單線程,而Scrapy爬蟲耗時幾乎不變,如圖3所示。
圖3 單線程和多線程爬取平均耗時對比圖Fig.3 Comparison chart of average time consumption of single thread and multi-thread crawling
表3 平均耗時對比Tab.3 Average time consumption comparison(單位:秒/1,000 頁)
5.2.4 反爬蟲規(guī)則下爬蟲登錄對比分析
目前,很多網(wǎng)站具有一定的反爬蟲機(jī)制,但對網(wǎng)絡(luò)爬蟲的相關(guān)研究,除robots這一“君子協(xié)定”外,并無相關(guān)的法律法規(guī)限制[8]。研究發(fā)現(xiàn)“中國裁判文書網(wǎng)”設(shè)置的反爬蟲機(jī)制嚴(yán)謹(jǐn),故以此作為實(shí)驗(yàn)對象對比不同爬蟲技術(shù)的繞過效果。
在手動測試中,打開網(wǎng)頁輸入用戶名、密碼并多次登錄網(wǎng)站后,會跳出登錄驗(yàn)證網(wǎng)頁,必須正確輸入驗(yàn)證碼才允許操作人員登錄。在Selenium技術(shù)開發(fā)的網(wǎng)絡(luò)爬蟲測試中,采用“程序睡眠+鍵盤輸入+自動填寫”進(jìn)行繞過登錄。首先啟動爬蟲程序調(diào)用本地瀏覽器直接訪問驗(yàn)證網(wǎng)頁,使用time.sleep()方法讓爬蟲進(jìn)程睡眠20 s,以提供鍵盤輸入信息的操作時間;其次直接手動在瀏覽器輸入驗(yàn)證碼證實(shí)非機(jī)器人行為,等睡眠結(jié)束后程序再調(diào)用click()方法自動執(zhí)行確認(rèn)按鈕,實(shí)現(xiàn)驗(yàn)證并跳轉(zhuǎn)到登錄頁面;再次使用find_element()和send_keys()方法定位文本框并自動填入用戶名和密碼;最后調(diào)用click()方法點(diǎn)擊登錄按鈕,完成爬蟲模擬登錄。爬蟲登錄網(wǎng)站獲取到用戶的Cookies后,可以應(yīng)用Cookies信息在其他爬蟲技術(shù),實(shí)現(xiàn)網(wǎng)頁數(shù)據(jù)定制化爬取。
在模擬登錄過程中,Selenium會打開一個瀏覽器,操作頁面全程實(shí)時可視化,顯現(xiàn)爬蟲對網(wǎng)頁的操作及元素變化,包括文本填寫、頁面跳轉(zhuǎn)、新建網(wǎng)頁等。由于網(wǎng)頁中存在隨機(jī)驗(yàn)證碼進(jìn)行非機(jī)器人操作驗(yàn)證,如果使用Requests、Scrapy技術(shù)開發(fā)的網(wǎng)絡(luò)爬蟲,則無法通過自動填報(bào)驗(yàn)證碼信息突破網(wǎng)站的反爬蟲機(jī)制。
本文研究了基于Python的Requests、Scrapy和Selenium爬蟲技術(shù),開發(fā)實(shí)現(xiàn)了單線程、多線程等6 個網(wǎng)絡(luò)爬蟲程序,驗(yàn)證了不同爬蟲技術(shù)之間的性能和技術(shù)實(shí)現(xiàn)差異。從實(shí)驗(yàn)數(shù)據(jù)來看,在排除其他因素干擾的情況下,只考慮爬取速度,則Requests技術(shù)、Scrapy技術(shù)單線程爬取網(wǎng)頁數(shù)據(jù)速度相當(dāng),并且遠(yuǎn)快于Selenium技術(shù)。若使用多線程爬取,Scrapy技術(shù)的爬取速度遠(yuǎn)快于Requests技術(shù),Selenium技術(shù)的爬取速度依舊最慢且性能表現(xiàn)很不理想。在考慮爬取速度的基礎(chǔ)上,結(jié)合3 個爬蟲技術(shù)的特征,可得出Requests技術(shù)爬取速度中規(guī)中矩,在Python內(nèi)置模塊的基礎(chǔ)上高度封裝了HTTP庫,入門簡單,對面向深度定制或小批量數(shù)據(jù)的爬蟲開發(fā)更為合適;Scrapy使用了異步網(wǎng)絡(luò)框架代碼,既簡化了代碼邏輯,又提高了開發(fā)效率,線程并發(fā)性能顯而易見,但代碼的自定義開發(fā)要契合Scrapy框架,遇到目標(biāo)數(shù)據(jù)涉及多個關(guān)聯(lián)URL,則開發(fā)不夠靈活,入門稍難,偏向適用于開發(fā)網(wǎng)站級別的網(wǎng)絡(luò)爬蟲,不適合深度定制;Selenium技術(shù)開發(fā)的網(wǎng)絡(luò)爬蟲,本質(zhì)上是驅(qū)動瀏覽器對目標(biāo)站點(diǎn)發(fā)送請求,瀏覽器在訪問目標(biāo)站點(diǎn)后,需要把HTML、CSS、JS等靜態(tài)資源加載完畢,因而整體效率在3 個技術(shù)中最低,但其會解析執(zhí)行目標(biāo)網(wǎng)頁的CSS、JS代碼,可以避開一系列復(fù)雜的通信流程,具有繞過復(fù)雜的反爬蟲機(jī)制能力,這方面的能力優(yōu)于Requests和Scrapy已被證實(shí)。網(wǎng)絡(luò)爬蟲的實(shí)際開發(fā)遇到的網(wǎng)站場景較為復(fù)雜、多樣,要根據(jù)不同業(yè)務(wù)需求選擇不同的爬蟲技術(shù),一項(xiàng)系統(tǒng)的業(yè)務(wù)往往要多種爬蟲技術(shù)配合使用才能達(dá)到獲取數(shù)據(jù)的目的。