從本篇博客開始,我們將進(jìn)入《爬蟲 120 例》的反爬章節(jié),給大家準(zhǔn)備了 20 篇反爬案例,一次學(xué)到位。
@[toc]
反爬理論知識(shí)
通過(guò)前面的爬蟲程序,你或許已經(jīng)注意到,對(duì)于目標(biāo)站點(diǎn)來(lái)說(shuō),爬蟲程序是機(jī)器訪問(wèn),從目標(biāo)站點(diǎn)的角度來(lái)看,爬蟲帶來(lái)的流量都是“垃圾流量”,是完全沒有價(jià)值的(刷量類爬蟲除外)。
為了屏蔽這些垃圾流量,或者為了降低自己服務(wù)器壓力,避免被爬蟲程序影響到正常人類的使用,開發(fā)者會(huì)研究各種各樣的手段,去反爬蟲。
爬蟲與反爬蟲是一對(duì)共生關(guān)系,有爬蟲工程師,就必然存在反爬工程師,很多時(shí)候,爬蟲工程師與反爬工程師都在斗智斗勇。
反爬沒有特定的分類,如果一個(gè)網(wǎng)站上了反爬代碼,一般情況下會(huì)使用幾種反爬措施搭配使用。
服務(wù)器驗(yàn)證請(qǐng)求信息類爬蟲
本系列的博客從最簡(jiǎn)單的反爬手段開始學(xué)習(xí),入門級(jí)反爬:“User-Agent” 用戶代理反爬。
User-Agent
用戶代理(User-Agent),表示的是用戶的瀏覽器相關(guān)信息,該反爬邏輯是通過(guò)服務(wù)器端驗(yàn)證請(qǐng)求頭中的 User-Agent 參數(shù),然后區(qū)分是爬蟲程序還是正常的瀏覽器訪問(wèn)。
訪問(wèn)任意網(wǎng)站,喚醒開發(fā)者工具,然后在控制臺(tái)中輸入 navigator.userAgent,就可以獲取到 UA 字符串(User-Agent 字符串)。

UA 字符串的格式一般可以這么理解:
平臺(tái) 引擎版本 瀏覽器版本信息
如果在詳細(xì)分解,可以得到如下格式:
瀏覽器標(biāo)識(shí) (操作系統(tǒng)標(biāo)識(shí);加密等級(jí);瀏覽器語(yǔ)言) 引擎版本 瀏覽器版本信息
這樣你在看上圖所示的內(nèi)容,就比較容易理解其含義了。
Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
在不同的瀏覽器測(cè)試,你會(huì)發(fā)現(xiàn) UA 字符串都以 Mozilla 開頭,這是由于歷史上的瀏覽器大戰(zhàn),導(dǎo)致的遺留問(wèn)題。
下面對(duì)比市面上主流的三款瀏覽器的 UA 字符串。
# 谷歌瀏覽器
Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
# 火狐瀏覽器
Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0
# IE11 瀏覽器
Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; rv:11.0) like Gecko
分析上述內(nèi)容中的相關(guān)數(shù)據(jù)含義
-
Mozilla/5.0:表示瀏覽器; -
Windows NT 6.1:操作系統(tǒng),我這里得到的是 Windows 7 操作系統(tǒng); -
Win64/WOW64:64 位操作系統(tǒng); -
x64:發(fā)行版本; -
N,I,U:加密等級(jí),這里沒有出現(xiàn); -
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36:這個(gè)如果你去研究,也有很多趣事,不過(guò)咱們理解其是瀏覽器的版本就可以了。
有了基本的認(rèn)知之后,我們就可以任意的去編寫不同的瀏覽器標(biāo)識(shí)了(多數(shù)時(shí)候是從開發(fā)者工具中直接復(fù)制)
相應(yīng)的,服務(wù)器也能從這個(gè)字符串中,識(shí)別出訪問(wèn)它的瀏覽器相關(guān)信息(其實(shí)操作系統(tǒng)的信息也會(huì)被攜帶過(guò)去,甚至它可以驗(yàn)證該 UA 字段是否復(fù)合特定的規(guī)則)
案例實(shí)操環(huán)節(jié)
拿 CSDN 熱榜進(jìn)行測(cè)試,如果不設(shè)置 UA 字段,你將獲取不到任何返回?cái)?shù)據(jù),你可以將下述 headers 置為空值,然后查看運(yùn)行結(jié)果。
import requests
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
}
res = requests.get('https://blog.csdn.net/phoenix/web/blog/hot-rank?page=0&pageSize=25', headers=headers)
print(res.text)
User-Agent 生成
可以使用 Python 第三方庫(kù),pip install fake_useragent,也可以自己維護(hù)一個(gè) UA 類。
與 User-Agent 參數(shù)相同的還有 HOST 與 Referer,都可以認(rèn)為的設(shè)置一些信息進(jìn)行反爬。
Cookie 反爬蟲
使用 Cookie 驗(yàn)證,也是常見的反爬,由于目標(biāo)站點(diǎn)可遇不可求,所以接下來(lái)的內(nèi)容從理論層面說(shuō)明,在后續(xù)會(huì)結(jié)合復(fù)雜的案例進(jìn)行實(shí)操。
Cookie 反爬蟲最簡(jiǎn)單的手段
服務(wù)器端使用特殊的 Cookie 值進(jìn)行驗(yàn)證,如果發(fā)現(xiàn)傳遞過(guò)去的 Cookie 值不存在,或者不符合生成規(guī)范,則不返回?cái)?shù)據(jù)。
例如服務(wù)器驗(yàn)證固定 Cookie 字段,在前文獲取熱榜代碼中,如果你不攜帶某些 Cookie 值,那得到的就不是完整的數(shù)據(jù)(可自行測(cè)試,差異值為 username)。
還有一種情況是驗(yàn)證 Cookie 是否符合某種格式,例如 Cookie 由 JS 動(dòng)態(tài)生成,而且復(fù)合某種潛在(開發(fā)者約定)的規(guī)則,那該 Cookie 值傳遞到后臺(tái)之后,后臺(tái)工程師直接驗(yàn)證該值即可實(shí)現(xiàn)反爬效果,例如 Cookie 規(guī)則為 123abc123,前面 3 個(gè)隨機(jī)數(shù),后面 3 個(gè)隨機(jī)數(shù),中間三個(gè)隨機(jī)小寫字母,那后臺(tái)工程師就可以通過(guò)正則驗(yàn)證客戶端傳遞的 Cookie 值,是否復(fù)合規(guī)則,不符合,直接返回異常信息。
當(dāng)然這種手段很容易被識(shí)別出來(lái),進(jìn)一步還可以加入時(shí)間戳,后臺(tái)工程師拿到 Cookie 中的時(shí)間戳之后,驗(yàn)證當(dāng)前時(shí)間的差值,如果超過(guò)了某個(gè)值,也可以認(rèn)為該 Cookie 是偽造的。
Cookie 還被用于用戶身份的驗(yàn)證,例如很多站點(diǎn)的數(shù)據(jù)只有登錄之后才可以訪問(wèn),原因是 Cookie 記錄了用戶信息,Cookie 的這個(gè)應(yīng)用場(chǎng)景比較多,例如華為云博客的系統(tǒng)消息頁(yè)面
https://developer.huaweicloud.com/usercenter/mysysmessage
點(diǎn)擊之后會(huì)跳轉(zhuǎn)到登錄頁(yè)面,但如果你在請(qǐng)求頭攜帶 Cookie 訪問(wèn),則得到對(duì)應(yīng)內(nèi)容,其中最重要的一個(gè) Cookie 字段是 HWS_ID,測(cè)試代碼如下,你可以從開發(fā)者工具中復(fù)制出對(duì)應(yīng)的 Cookie 字段訪問(wèn)該頁(yè)面。
import requests
from lxml import etree
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36",
"cookie": '你的HWS_ID Cookie值;'
}
res = requests.get('https://developer.huaweicloud.com/usercenter/mysysmessage', headers=headers, allow_redirects=False)
with open("./1.html", "w", encoding="utf-8") as f:
f.write(res.text)
elements = etree.HTML(res.text)
print(elements.xpath("http://title/text()"))
訂閱時(shí)間
今天是持續(xù)寫作的第 <font color=red>269</font> / 365 天。
可以<font color=#04a9f4>關(guān)注</font>我,<font color=#04a9f4>點(diǎn)贊</font>我、<font color=#04a9f4>評(píng)論</font>我、<font color=#04a9f4>收藏</font>我啦。
更多精彩