韓 貝,馬明棟,王得玉
(1.南京郵電大學(xué) 通信與信息工程學(xué)院,江蘇 南京 210003;2.南京郵電大學(xué) 地理與生物信息學(xué)院,江蘇 南京 210003)
信息時(shí)代下,每天有數(shù)以萬計(jì)網(wǎng)絡(luò)爬蟲[1]程序在萬維網(wǎng)上自動(dòng)運(yùn)行,搜集大量數(shù)據(jù)。如何有效阻止這些爬蟲是每個(gè)網(wǎng)站構(gòu)建者必須要考慮的事情,而如何以低成本突破網(wǎng)站對爬蟲的限制,繼續(xù)搜集數(shù)據(jù)則是每個(gè)爬蟲使用者思考的問題,這場在反爬蟲[2]和爬蟲之間的較量,從未停歇過。文中結(jié)合實(shí)際網(wǎng)站來分析反爬蟲的一些常用手段,如IP限制、訪問頻率控制等[3];同時(shí)基于爬蟲使用者經(jīng)常使用的開源爬蟲框架Scrapy,來說明爬蟲使用者又是如何來化解網(wǎng)站限制的。
被稱為膠水語言的Python,具有豐富和強(qiáng)大的庫,如requests、urllib、scrapy和pyquery等[4],其中scrapy庫應(yīng)用最為廣泛。Scrapy是Python語言開發(fā),為爬取萬維網(wǎng)上網(wǎng)站數(shù)據(jù)而設(shè)計(jì)的開源應(yīng)用型框架,可以應(yīng)用在數(shù)據(jù)挖掘以及信息處理等方面。借助Scrapy,可以方便快速地按照自己的需求,保存網(wǎng)頁關(guān)鍵數(shù)據(jù)為任意數(shù)據(jù)格式。
Scrapy是由Scrapy Engine、Spiders、Item Pipeline、調(diào)度器、下載器、下載器中間件和Spider中間件構(gòu)成[5],具體框架如圖1所示。
圖1 Scrapy框架
(1)Scrapy Engine:負(fù)責(zé)系統(tǒng)中數(shù)據(jù)流動(dòng),維護(hù)框架各個(gè)部分正常運(yùn)作;
(2)Spiders:處理下載的網(wǎng)頁信息,提取結(jié)構(gòu)化數(shù)據(jù),獲取需要額外跟進(jìn)的URL;
(3)Item Pipeline:處理Spiders提取出來的數(shù)據(jù);
(4)調(diào)度器:控制整個(gè)URL請求順序;
(5)下載器:從瀏覽器中下載相應(yīng)網(wǎng)頁信息;
(6)下載器中間件:Scrapy Engine和下載器之間的鉤子,用于修改Scrapy請求和響應(yīng);
(7)Spider中間件:Scrapy Engine和Spiders之間的鉤子,處理Spider輸入輸出。
Scrapy首先從Spiders中拿到第一個(gè)要請求的URL,通過調(diào)度器調(diào)度下載器進(jìn)行頁面下載,下載的頁面信息由Spiders進(jìn)行處理。Spiders從頁面中提取數(shù)據(jù)信息并交給Item Pipeline,而提取的URL信息則通過Scrapy Engine交由調(diào)度器處理。Item Pipeline接收到Spiders數(shù)據(jù),對數(shù)據(jù)進(jìn)行處理,處理之后保存為制定的數(shù)據(jù)格式。調(diào)度器獲取URL之后,重復(fù)以上操作,直至調(diào)度器里URL隊(duì)列為空時(shí),結(jié)束爬蟲運(yùn)行[6]。
爬蟲爬取某個(gè)網(wǎng)站數(shù)據(jù)時(shí),會發(fā)生短時(shí)間內(nèi)發(fā)出大量訪問請求,而請求IP都是同一個(gè)的情況。因此,網(wǎng)站會設(shè)置訪問閾值,針對超過閾值的異常IP,網(wǎng)站可以禁止其訪問[7]。但是由于大量用戶公網(wǎng)IP相同,這種方法容易誤傷普通用戶,所以,一般采取禁止一段時(shí)間訪問。
目前大部分網(wǎng)站會設(shè)置會員限制,部分?jǐn)?shù)據(jù)及操作只能登陸賬號才能有權(quán)限訪問,這一做法限制了普通爬蟲隨意訪問。但深層爬蟲[8]可以通過攜帶cookies信息,突破網(wǎng)站權(quán)限設(shè)置,繼續(xù)爬取數(shù)據(jù)。網(wǎng)站可以實(shí)時(shí)監(jiān)測賬號訪問頻率,設(shè)置訪問頻率限制,當(dāng)某一賬號訪問超過限制,即可視為異常賬號,禁止其訪問。
網(wǎng)站通過瀏覽器請求信息中的cookies信息[9]來判斷該請求是否有權(quán)限訪問核心數(shù)據(jù),一般網(wǎng)站直接輸入用戶的賬號和密碼即可成功登陸并獲取cookies信息。這一操作爬蟲可通過分析網(wǎng)頁Html源碼,模擬發(fā)送請求,就能正常獲取cookies信息。于是部分網(wǎng)站設(shè)置了驗(yàn)證碼等驗(yàn)證方式,只有成功輸入驗(yàn)證碼,才能獲取cookies信息。同時(shí),部分網(wǎng)站還會設(shè)置Session方式進(jìn)行賬號認(rèn)證,只有獲取服務(wù)器對用戶的唯一標(biāo)識ID,才能得到cookies信息。
早期簡單網(wǎng)頁采取靜態(tài)網(wǎng)頁方式,網(wǎng)頁所有內(nèi)容都包含在Html源碼里,爬蟲通過偽造請求,獲取網(wǎng)頁Html源碼并分析Html源碼,就能提取出自己想要的數(shù)據(jù)。
隨著網(wǎng)頁技術(shù)的發(fā)展,動(dòng)態(tài)網(wǎng)頁[10]逐漸成為主流。動(dòng)態(tài)網(wǎng)頁頁面源碼相對于靜態(tài)網(wǎng)頁而言,顯示的內(nèi)容可以隨著時(shí)間、環(huán)境或者數(shù)據(jù)庫操作的結(jié)果而發(fā)生改變。如果爬蟲只是單純分析Html源碼,將無法獲取有效數(shù)據(jù)。
爬蟲需要在短時(shí)間內(nèi)發(fā)出大量訪問請求,若爬蟲一直使用同一IP地址,就會被網(wǎng)站禁用,為避免這種情況發(fā)生,使用IP代理[11]是非常有必要的。爬蟲IP代理有付費(fèi)和免費(fèi)兩種,付費(fèi)IP質(zhì)量較高,爬蟲直接請求相關(guān)付費(fèi)接口即可獲取不同IP;免費(fèi)IP質(zhì)量較低,容易出現(xiàn)連接失敗的情況。下面,以西刺代理網(wǎng)站免費(fèi)IP為例,構(gòu)建自己的IP代理池,其架構(gòu)如圖2所示。
圖2 IP代理池架構(gòu)
使用詳解:
(1)分析西刺代理網(wǎng)站頁面源碼,從源碼中找到需要提取的IP地址數(shù)據(jù)和端口信息;
(2)利用Scrapy構(gòu)建西刺代理網(wǎng)站爬蟲,首先創(chuàng)建spiders,定義要爬取的西刺代理網(wǎng)站地址,通過spiders的css選擇器,提取出需要的數(shù)據(jù),實(shí)現(xiàn)獲取和提取功能,將數(shù)據(jù)存入items中;
(3)對items中的數(shù)據(jù)進(jìn)行驗(yàn)證處理,實(shí)現(xiàn)對提取出的數(shù)據(jù)進(jìn)行過濾。導(dǎo)入requests模塊,使用爬取出來的IP代理去請求百度網(wǎng)址,若返回的狀態(tài)碼為200,則證明該IP代理有效,將該IP地址存入到mongoDB數(shù)據(jù)庫中,反之則丟棄該數(shù)據(jù);
(4)爬蟲若需要使用IP代理池中的IP數(shù)據(jù),只需要修改下載器中間件類中process_request方法,在該方法中調(diào)用request.meta設(shè)置IP代理,IP代理的具體數(shù)據(jù)可從mongoDB數(shù)據(jù)庫中查找得到,運(yùn)行該爬蟲就能實(shí)現(xiàn)更換IP地址的功能。
部分網(wǎng)站數(shù)據(jù)需要登陸獲取權(quán)限才能繼續(xù)訪問網(wǎng)頁,針對這種情況,爬蟲需要構(gòu)造并攜帶cookies信息。同時(shí)網(wǎng)站會對賬號訪問記錄進(jìn)行統(tǒng)計(jì),超過一定頻率就會被標(biāo)為異常賬戶,爬蟲重復(fù)使用單一的cookies信息很容易造成賬號異常而無法使用。解決辦法是構(gòu)建自己的cookies池[12],使用爬蟲時(shí),按一定頻率來切換cookies信息。需要注意的是,部分網(wǎng)站的cookies信息具有時(shí)效性,需考慮更新問題。下面以伯樂在線為例進(jìn)行詳細(xì)說明,構(gòu)建的cookies池架構(gòu)如圖3所示。
使用詳解:
(1)需要注冊伯樂在線賬號,將注冊好的賬號密碼存入文檔;
圖3 cookies架構(gòu)
(2)分析伯樂在線登陸頁面源碼,伯樂在線登陸過程較為簡單,直接將賬號密碼用post方法請求就可獲取cookies信息;
(3)基于Scrapy框架,構(gòu)建爬蟲,編寫spiders代碼,改寫類中parse方法,調(diào)用mongoDB中賬號密碼數(shù)據(jù),用post請求重復(fù)請求登陸頁面,獲取cookies信息,將提取出來的cookies信息存入mongoDB;
(4)若要使用cookies信息,只需要改寫下載器中間件的代碼,需要注意cookies的時(shí)效性,要定時(shí)更新mongoDB中的cookies信息。
上面分析的伯樂在線登陸過程較簡單,但是部分網(wǎng)站登陸過程遠(yuǎn)比這個(gè)復(fù)雜,例如登陸github網(wǎng)頁,需要獲取存儲在token字段中的Session標(biāo)識。而知乎的登陸過程則更為復(fù)雜,在有Session標(biāo)識的同時(shí),還需要正確輸入驗(yàn)證碼才能登陸成功。下面以知乎登陸過程為例,詳細(xì)說明爬蟲是如何處理這些登陸問題的。
使用詳解:
(1)分析知乎登陸頁面源碼,可以發(fā)現(xiàn)其中有一個(gè)xsrf值,登陸時(shí)需包含該值,同時(shí)還有驗(yàn)證碼校驗(yàn),必須輸入正確驗(yàn)證碼才能成功登陸;
(2)用Scrapy框架編寫爬蟲,在spiders文件里的parse方法中,提取登陸頁面源碼里的xsrf值,將該值寫入post方法中;
(3)對于登陸頁面驗(yàn)證碼,可以采用人工輸入或者自動(dòng)識別兩種方法。若采用人工輸入,首先獲取驗(yàn)證碼圖片,用PIL庫中Image類的show方法,展示圖片,然后手動(dòng)輸入。若采用自動(dòng)識別,可接入打碼平臺或者使用機(jī)器學(xué)習(xí)來識別,自動(dòng)輸入;
(4)解決以上兩個(gè)問題,爬蟲便可成功登陸,獲取cookies信息并進(jìn)行數(shù)據(jù)提取。
隨著前端技術(shù)的不斷發(fā)展,現(xiàn)在部分網(wǎng)站頁面采用動(dòng)態(tài)頁面,需要進(jìn)行一些頁面操作,動(dòng)態(tài)加載出數(shù)據(jù)。可以通過分析網(wǎng)頁的Ajax請求,用爬蟲直接請求其對應(yīng)接口獲取數(shù)據(jù),但是這種分析較復(fù)雜,更簡便的方法是使用Selenium[13]。Selenium是一個(gè)自動(dòng)化測試工具,主要用來測試Web應(yīng)用,能夠在瀏覽器中模擬用戶操作。下面以淘寶為例,詳細(xì)說明其使用方法。
(1)分析淘寶主頁面,通過在檢索框中輸入檢索詞,點(diǎn)擊確定,就能得到相關(guān)商品信息;
(2)構(gòu)建基于Scrapy爬蟲,改寫下載器中間件文件,在該文件中導(dǎo)入Selenium模塊,創(chuàng)建Selenium的Chrome對象;
(3)修改類中process_request方法,添加元素等待語句,一旦頁面元素加載出來,就進(jìn)行填入檢索詞和點(diǎn)擊按鈕兩個(gè)操作;
(4)運(yùn)行以上爬蟲,可以看到Chrome瀏覽器被自動(dòng)打開,自動(dòng)進(jìn)行填入檢索詞和點(diǎn)擊按鈕兩個(gè)操作,頁面數(shù)據(jù)正常加載出來,爬蟲就可以提取加載出來的數(shù)據(jù)。
爬蟲作為獲取數(shù)據(jù)的重要工具之一,廣泛應(yīng)用于各種網(wǎng)站。據(jù)統(tǒng)計(jì),網(wǎng)絡(luò)上百分之六十的流量都是爬蟲產(chǎn)生的。文中僅僅列舉了一些簡單的爬蟲和反爬蟲方法,指出網(wǎng)站為保護(hù)數(shù)據(jù)所采取的措施,以及爬蟲又是如何突破重重限制的。如今,爬蟲和反爬蟲之間的較量愈演愈烈,還有更復(fù)雜的爬蟲和反爬技術(shù)值得去探討。