導(dǎo)讀:在互聯(lián)網(wǎng)上爬取數(shù)據(jù)的過(guò)程中難免出現(xiàn)ip被封或者服務(wù)器返回403等等,這可能是你被網(wǎng)站檢測(cè)為爬蟲(chóng)而采取的反爬措施,本文主要總結(jié)了一些常見(jiàn)的情況及規(guī)避的措施。
網(wǎng)絡(luò)爬蟲(chóng),是一種自動(dòng)獲取網(wǎng)頁(yè)內(nèi)容的程序,它存在的時(shí)間差不多和互聯(lián)網(wǎng)存在的時(shí)間一樣長(zhǎng)。然而互聯(lián)網(wǎng)上大量的爬蟲(chóng)也給網(wǎng)站帶來(lái)了很大的困擾,嚴(yán)重影響了網(wǎng)站的正常運(yùn)行,甚至威脅到數(shù)據(jù)及系統(tǒng)的安全,于是各式各樣的反爬蟲(chóng)技術(shù)應(yīng)運(yùn)而生。在程序員的互相博弈之下,兩種技術(shù)都得到了極大的發(fā)展,比如12306的驗(yàn)證碼發(fā)展史,就是一場(chǎng)經(jīng)典的反爬蟲(chóng)技術(shù)發(fā)展史,以至于12306從最初特別簡(jiǎn)單的驗(yàn)證碼發(fā)展到如今令人發(fā)指的驗(yàn)證碼。
在做網(wǎng)絡(luò)爬蟲(chóng)時(shí),經(jīng)??赡軙?huì)遇到數(shù)據(jù)顯示在瀏覽器上但卻抓取不出來(lái),也許是向服務(wù)器提交自認(rèn)為已經(jīng)處理得很好的表單卻被拒絕,也許是自己的賬號(hào)或者IP地址不知道什么原因直接被網(wǎng)站封殺,無(wú)法繼續(xù)訪問(wèn)。此時(shí),最可能出現(xiàn)的情況是:對(duì)方使用了反爬蟲(chóng)技術(shù),有意不讓爬蟲(chóng)抓取信息。接下來(lái)本文就介紹一些常見(jiàn)的克服網(wǎng)站阻止自動(dòng)采集的方法來(lái)突破這些限制。
1.構(gòu)造合理的 HTTP 請(qǐng)求頭
HTTP 的請(qǐng)求頭是在你每次向網(wǎng)絡(luò)服務(wù)器發(fā)送請(qǐng)求時(shí),傳遞的一組屬性和配置信息。HTTP 定義了十幾種古怪的請(qǐng)求頭類(lèi)型,不過(guò)大多數(shù)都不常用。只有下面的七個(gè)字段被大多數(shù)瀏覽器用來(lái)初始化所有網(wǎng)絡(luò)請(qǐng)求。雖然網(wǎng)站可能會(huì)對(duì)HTTP請(qǐng)求頭的每個(gè)屬性都進(jìn)行檢查,但是通常真正重要的參數(shù)就是User-Agent。無(wú)論是什么樣的爬蟲(chóng),一定要記得把User-Agent屬性設(shè)置成不容易引起懷疑的內(nèi)容,比如如果你用python的urllib標(biāo)準(zhǔn)庫(kù)時(shí),它的User-Agent可能就會(huì)是Python-urllib/3.4,這樣就很容易被禁。另外,如果你正在處理一個(gè)警覺(jué)性非常高的網(wǎng)站,就要注意那些經(jīng)常用卻很少檢查的請(qǐng)求頭,比如 Accept-Language屬性,也許它正是那個(gè)網(wǎng)站判斷你是否是人類(lèi)訪問(wèn)者的關(guān)鍵。還有一部分網(wǎng)站會(huì)對(duì)Referer進(jìn)行檢測(cè),比如一些資源網(wǎng)站的防盜鏈就是檢測(cè)Referer。如果遇到了這類(lèi)反爬蟲(chóng)機(jī)制,可以直接在爬蟲(chóng)中添加Headers,將瀏覽器的User-Agent復(fù)制到爬蟲(chóng)的Headers中;或者將Referer值修改為目標(biāo)網(wǎng)站域名。對(duì)于檢測(cè)Headers的反爬蟲(chóng),在爬蟲(chóng)中修改或者添加Headers就能很好的繞過(guò)。
另外,請(qǐng)求頭還可能讓網(wǎng)站改變內(nèi)容的布局樣式。例如,用移動(dòng)設(shè)備瀏覽網(wǎng)站時(shí),通常會(huì)看到一個(gè)沒(méi)有廣告、Flash以及其他干擾的簡(jiǎn)化的網(wǎng)站版本。因此,把你的請(qǐng)求頭User-Agent改成下面這樣,也許就可以看到一個(gè)更容易采集的網(wǎng)站了。
User-Agent:Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_2 like Mac OS X) App leWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53
2.設(shè)置cookie
cookie其實(shí)是儲(chǔ)存在用戶(hù)終端的一些被加密的數(shù)據(jù),有些網(wǎng)站通過(guò)cookies來(lái)識(shí)別用戶(hù)身份,如果某個(gè)訪問(wèn)總是高頻率地發(fā)請(qǐng)求,很可能會(huì)被網(wǎng)站注意到,被懷疑為爬蟲(chóng),這時(shí)網(wǎng)站就可以通過(guò)cookie找到這個(gè)訪問(wèn)的用戶(hù)而拒絕其訪問(wèn)。對(duì)于這種情況可以通過(guò)禁用cookie,主動(dòng)阻止服務(wù)器寫(xiě)入。禁用cookie可以防止使用cookies識(shí)別爬蟲(chóng)的網(wǎng)站來(lái)禁掉我們。
但是采集某些網(wǎng)站時(shí)cookie是不可或缺的。要在一個(gè)網(wǎng)站上持續(xù)保持登錄狀態(tài),需要在多個(gè)頁(yè)面中保存一個(gè)cookie。有些網(wǎng)站不要求在每次登錄時(shí)都獲得一個(gè)新cookie,只要保存一個(gè)舊的已登錄的 cookie 就可以訪問(wèn)。
3.降低訪問(wèn)頻率
為了提高爬蟲(chóng)的效率,很多人在爬蟲(chóng)中使用多線程、異步等手段,使得爬蟲(chóng)在一個(gè)小時(shí)內(nèi)甚至可以訪問(wèn)數(shù)十萬(wàn)次頁(yè)面,給服務(wù)器帶來(lái)了不小的壓力,因此有一些防護(hù)措施較完備的網(wǎng)站就可能會(huì)阻止你快速地提交表單,或者快速地與網(wǎng)站進(jìn)行交互。即使沒(méi)有這些安全措施,用一個(gè)比普通人快很多的速度從一個(gè)網(wǎng)站下載大量信息也可能讓自己被網(wǎng)站封殺。
遇到這種網(wǎng)站,如果你對(duì)爬蟲(chóng)效率要求不高,可以嘗試降低爬蟲(chóng)訪問(wèn)速度,比如不再使用多線程技術(shù),每次訪問(wèn)后設(shè)置等待時(shí)間,限制每小時(shí)訪問(wèn)量等。比如在python中:
import time,random#導(dǎo)入包
time.sleep(random.randint(1,9))#設(shè)置時(shí)間間隔為隨機(jī)幾秒鐘
但如果你對(duì)爬蟲(chóng)效率要求比較高,每次訪問(wèn)都等待無(wú)法滿(mǎn)足要求,那么首先需要確定網(wǎng)站是根據(jù)什么條件進(jìn)行限制的,再想辦法去突破限制。比如很多網(wǎng)站都是通過(guò)IP來(lái)限制訪問(wèn)量的,那么就可以使用代理IP,每請(qǐng)求幾次就換一個(gè)IP,這樣就可以避免被禁了。
4.動(dòng)態(tài)頁(yè)面的反爬蟲(chóng)
上述的幾種情況大多都是出現(xiàn)在靜態(tài)頁(yè)面,還有一部分網(wǎng)站,我們需要爬取的數(shù)據(jù)是通過(guò)ajax請(qǐng)求得到,或者通過(guò)JavaScript生成的。對(duì)于這種情況,我們首先需要對(duì)網(wǎng)絡(luò)請(qǐng)求進(jìn)行分析,如果能夠找到ajax請(qǐng)求,也能分析出具體的參數(shù)和響應(yīng)的具體含義,我們就能采用上面的方法,直接模擬ajax請(qǐng)求,對(duì)響應(yīng)的json進(jìn)行分析得到需要的數(shù)據(jù)。
如果這種方法不行,或者需要處理JS,那么則可以采用selenium+phantomJS。PhantomJS是一個(gè)無(wú)界面的WebKit瀏覽器,除了沒(méi)有界面,基本和一般的瀏覽器一樣。Selenium是一個(gè)自動(dòng)化測(cè)試工具,它可以驅(qū)動(dòng)瀏覽器,兩者結(jié)合,雙劍合璧,從填寫(xiě)表單到點(diǎn)擊按鈕再到滾動(dòng)頁(yè)面,全部都可以模擬,不考慮具體的請(qǐng)求和響應(yīng)過(guò)程,只是完完整整的把人瀏覽頁(yè)面獲取數(shù)據(jù)的過(guò)程模擬一遍。 用這套框架幾乎能繞過(guò)大多數(shù)的反爬蟲(chóng),因?yàn)樗皇窃趥窝b成瀏覽器來(lái)獲取數(shù)據(jù)(上述的通過(guò)添加Headers一定程度上就是為了偽裝成瀏覽器),phantomJS本身就是一個(gè)沒(méi)有界面的瀏覽器,只是操控這個(gè)瀏覽器的不是人而是程序。利用selenium+phantomJS能干很多事情,cookie、JavaScript、header都能自動(dòng)處理,比如現(xiàn)在比較流行的滑動(dòng)式驗(yàn)證碼,就可以使用它們解決。
5.注意隱含輸入字段值
為了反爬蟲(chóng),一些網(wǎng)站會(huì)在html表單中故意添加隱藏元素,這些隱含字段可以讓字段的值對(duì)瀏覽器可見(jiàn),但是對(duì)用戶(hù)不可見(jiàn),除非看網(wǎng)頁(yè)源代碼。如果你爬著爬著就把隱藏元素都爬出來(lái)了,那么就很容易被網(wǎng)站識(shí)別出來(lái),只要被網(wǎng)站發(fā)現(xiàn),就有可能立馬被封賬號(hào)或者IP,所以在提交表單前一定要先看一下元素再進(jìn)行爬取。
比如下面這段html代碼:
<html><head>
<title>A bot-proof form</title>
<style>
body {overflow-x: hidden;}
.customHidden {
position: absolute;
right: 50000px;
}
</style>
<style type="text/css"></style>
</head>
<body>
<h2>A bot-proof form</h2>
<a style="display:none;">Go here!</a>
<a >Click me!</a>
<form>
<input type="hidden" name="phone" value="valueShouldNotBeModified">
<p><input type="text" name="email" class="customHidden" value="intentionallyBlank"></p>
<p><input type="text" name="firstName"></p>
<p><input type="text" name="lastName"></p>
<p><input type="submit" value="Submit"></p>
</form>
</body></html>
這段代碼包含了兩個(gè)鏈接,但是其中一個(gè)通過(guò)css隱藏了,一旦你訪問(wèn)了這個(gè)鏈接,可能就會(huì)中招。而在表單中,電話(huà)號(hào)碼字段name="phone"是一個(gè)隱含的輸入字段,郵箱地址字段name="email"是將元素向右移動(dòng)50000像素并隱藏滾動(dòng)條,這兩個(gè)對(duì)用戶(hù)而言都是不可見(jiàn)的。
處理這種頁(yè)面可以在訪問(wèn)前先進(jìn)行分析,也可以使用Selenium,通過(guò)is_displayed來(lái)判斷元素在頁(yè)面上是否可見(jiàn),從而避免被封禁。
6.使用代理
網(wǎng)絡(luò)爬蟲(chóng)幾乎所有的數(shù)據(jù)都是偽造的,但是有一項(xiàng)卻是不能作假的,那就是IP地址。因此很多網(wǎng)站為了防爬蟲(chóng),制定了一系列規(guī)則去封殺IP,簡(jiǎn)單粗暴又十分有效。如果你的IP地址被封,那么這時(shí)就該代理上場(chǎng)了。所謂代理就是介于用戶(hù)與網(wǎng)站之間的第三者:用戶(hù)先將請(qǐng)求發(fā)到代理,然后代理再發(fā)到服務(wù)器,這樣看起來(lái)就像是代理在訪問(wèn)那個(gè)網(wǎng)站了。這時(shí),服務(wù)器會(huì)將這次訪問(wèn)算到代理頭上。同時(shí)用多個(gè)代理的話(huà),單個(gè)IP的訪問(wèn)量就降下去了,于是就有可能逃過(guò)一劫。
python中的requests使用代理非常簡(jiǎn)單:
import requests
proxies = {
"http": "XXX.XX.XX.XX:XX",
}
print requests.get('http://www.ip181.com/',proxies=proxies).content
http://www.ip181.com 是一個(gè)可以檢測(cè)代理IP的網(wǎng)站,它可以檢測(cè)出你使用的ip是什么,正好可以用來(lái)檢驗(yàn)自己是否使用代理ip成功。
如果你有多個(gè)代理IP,那么可以建立一個(gè)IP池,每次隨機(jī)從IP池中選擇一個(gè)進(jìn)行訪問(wèn),如果訪問(wèn)失敗了,則將其從池中去除即可。
以上就是一些防止爬蟲(chóng)被封禁的常見(jiàn)情況和解決辦法??傊?,反爬蟲(chóng)的技術(shù)總是想方設(shè)法地去區(qū)分人和程序,所以防止被封禁的核心思想就是盡量偽裝成正常的用戶(hù),只要按著這個(gè)思想走,總能找到具體的方法。
參考文章:
http://www.toutiao.com/a6289159538663538946/
http://www.itdecent.cn/p/73697828b8f8
http://blog.163.com/zhuyunyun_work/blog/static/19611284020142594424758/
http://www.cnblogs.com/ShakeTian/articles/5957482.html
https://zhuanlan.zhihu.com/p/20520370?columnSlug=python-hacker