面向?qū)ο缶幊?/a>詳解">JavaScript面向?qū)ο缶幊?/a>詳解
1961
2025-03-31
開(kāi)篇
隨著 Python 和大數(shù)據(jù)的火熱,大量的工程師蜂擁而上,爬蟲技術(shù)由于易學(xué)、效果顯著首當(dāng)其沖的成為了大家追捧的對(duì)象,爬蟲的發(fā)展進(jìn)入了高峰期,因此給服務(wù)器帶來(lái)的壓力則是成倍的增加。企業(yè)或?yàn)榱吮WC服務(wù)的正常運(yùn)轉(zhuǎn)或?yàn)榱私档蛪毫εc成本,不得不使出各種各樣的技術(shù)手段來(lái)阻止爬蟲工程師們毫無(wú)節(jié)制的向服務(wù)器索取資源,我們將這種行為稱為『反爬蟲』。
『反爬蟲技術(shù)』是互聯(lián)網(wǎng)技術(shù)中為了限制爬蟲而產(chǎn)生的技術(shù)總稱,而反爬蟲的繞過(guò)則是所有爬蟲工程師要面對(duì)的問(wèn)題,也是中高級(jí)爬蟲工程師面試中最關(guān)注的方面。
問(wèn)題所在
但是在平時(shí)的交流中,筆者發(fā)現(xiàn)大多數(shù)的初級(jí)爬蟲工程師只會(huì)拿著網(wǎng)上別人寫的技術(shù)文章唾沫橫飛,除了知道在請(qǐng)求的時(shí)候偽造瀏覽器請(qǐng)求頭信息中的 User-Agent 以外,對(duì)于: * 為什么要這么做? * 這么做有什么好處? * 我可以用別的方法實(shí)現(xiàn)么? * 它的原理是怎么樣的? * 它是如何識(shí)別我的爬蟲的? * 我應(yīng)該用什么方式繞過(guò)它?
一無(wú)所知。如果你既不知道原理又不知道實(shí)現(xiàn)方式,那么當(dāng)目標(biāo)網(wǎng)站稍微調(diào)整一下反爬蟲策略的時(shí)候,你還是一臉懵逼
對(duì),就是一臉懵逼。
我也在嘗試著,能夠?qū)⑦@樣的知識(shí)分享出來(lái),讓大家在閑暇之余能夠通過(guò)這篇文章學(xué)習(xí)到反爬蟲知識(shí)中比較簡(jiǎn)單的反爬蟲原理和實(shí)現(xiàn)方法,再熟悉他的繞過(guò)操作。比如 User-Agent 反爬手段,了解它的原理并且親手實(shí)現(xiàn)反爬蟲,再親手繞過(guò)它。或許通過(guò)這個(gè)小小的案例,就可以打開(kāi)你思維的大門、撬開(kāi)你思路的下水道。
正文
上面是空談,下面是實(shí)踐。一位偉人曾經(jīng)表達(dá)過(guò)這么一個(gè)意思:
管你黑貓白貓,抓不到老鼠的貓,它就不是個(gè)好貓
什么是 User-Agent
User Agent中文名為用戶代理,簡(jiǎn)稱 UA,它是一個(gè)特殊字符串頭,使得服務(wù)器能夠識(shí)別客戶使用的操作系統(tǒng)及版本、CPU 類型、瀏覽器及版本、瀏覽器渲染引擎、瀏覽器語(yǔ)言、瀏覽器插件等。一些網(wǎng)站常常通過(guò)判斷 UA 來(lái)給不同的操作系統(tǒng)、不同的瀏覽器發(fā)送不同的頁(yè)面,因此可能造成某些頁(yè)面無(wú)法在某個(gè)瀏覽器中正常顯示,但通過(guò)偽裝 UA 可以繞過(guò)檢測(cè)。瀏覽器向服務(wù)器發(fā)起請(qǐng)求的流程圖,可以用下圖表示:
這里以火狐瀏覽器和谷歌瀏覽器為例,UA 的格式或者說(shuō)表現(xiàn)形式是這樣的:
Firefox 的 User-Agent:
Mozilla/5.0?(Macintosh;?Intel?Mac?OS?X?10.13;?rv:63.0)?Gecko/20100101?Firefox/63.0
Chrome 的 User-Agent:
Mozilla/5.0?(Macintosh;?Intel?Mac?OS?X?10_13_3)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/70.0.3538.77?Safari/537.36
User-Agent 在網(wǎng)絡(luò)請(qǐng)求中充當(dāng)什么角色?
在網(wǎng)絡(luò)請(qǐng)求當(dāng)中,User-Agent 是標(biāo)明身份的一種標(biāo)識(shí),服務(wù)器可以通過(guò)請(qǐng)求頭參數(shù)中的 User-Agent 來(lái)判斷請(qǐng)求方是否是瀏覽器、客戶端程序或者其他的終端(當(dāng)然,User-Agent 的值為空也是允許的,因?yàn)樗皇潜匾獏?shù))。
瀏覽器的角色,如上圖方框中所示,那么 User-Agent 的角色,就是表明身份。
為什么反爬蟲會(huì)選擇 User-Agent 這個(gè)參數(shù)呢?
從上面的介紹中,可以看出它是終端的身份標(biāo)識(shí)。意味著服務(wù)器可以清楚的知道,這一次的請(qǐng)求是通過(guò)火狐瀏覽器發(fā)起的,還是通過(guò) IE 瀏覽器發(fā)起的,甚至說(shuō)是否是應(yīng)用程序(比如 Python )發(fā)起的。
網(wǎng)站的頁(yè)面、動(dòng)效和圖片等內(nèi)容的呈現(xiàn)是借助于瀏覽器的渲染功能實(shí)現(xiàn)的,瀏覽器是一個(gè)相對(duì)封閉的程序,因?yàn)樗_保數(shù)據(jù)的成功渲染,所以用戶無(wú)法從瀏覽器中大規(guī)模的、自動(dòng)化的獲取內(nèi)容數(shù)據(jù)。
而爬蟲卻不是這樣的,爬蟲生來(lái)就是為了獲取網(wǎng)絡(luò)上的內(nèi)容并將其轉(zhuǎn)化為數(shù)據(jù)。這是兩種截然不同的方式,你也可以理解為通過(guò)編寫代碼來(lái)大規(guī)模的、自動(dòng)化的獲取內(nèi)容數(shù)據(jù),這是一種騷操作。
回到正題,為什么會(huì)選擇 User-Agent 這個(gè)參數(shù)呢?
因?yàn)榫幊陶Z(yǔ)言都有默認(rèn)的標(biāo)識(shí),在發(fā)起網(wǎng)絡(luò)請(qǐng)求的時(shí)候,這個(gè)標(biāo)識(shí)在你毫不知情的情況下,作為請(qǐng)求頭參數(shù)中的 User-Agent 值一并發(fā)送到服務(wù)器。比如 Python 語(yǔ)言通過(guò)代碼發(fā)起網(wǎng)絡(luò)請(qǐng)求時(shí), User-Agent 的值中就包含 Python 。同樣的,Java 和 PHP 這些語(yǔ)言也都有默認(rèn)的標(biāo)識(shí)。
反爬蟲的黑名單策略
既然知道編程語(yǔ)言的這個(gè)特點(diǎn),再結(jié)合實(shí)際的需求,那么反爬蟲的思路就出來(lái)了。這是一中黑名單策略,只要出現(xiàn)在黑名單中的請(qǐng)求,都視為爬蟲,對(duì)于此類請(qǐng)求可以不予處理或者返回相應(yīng)的錯(cuò)誤提示。
為什么用黑名單策略不用白名單策略?
現(xiàn)實(shí)生活中,瀏覽器類型繁多(火狐瀏覽器、谷歌瀏覽器、360 瀏覽器、傲游瀏覽器、歐普拉瀏覽器、世界之窗瀏覽器、QQ 瀏覽器等),
想要將所有的瀏覽器品牌、類型以及對(duì)應(yīng)的標(biāo)識(shí)收集并放到名單中,那是不實(shí)際的,假如漏掉了哪一種,那么對(duì)網(wǎng)站來(lái)說(shuō)是一種損失。
再者說(shuō)來(lái),很多的服務(wù)并不僅僅開(kāi)放給瀏覽器,有些時(shí)候這些服務(wù)以 API 的形式向應(yīng)用程序提供服務(wù),比如安卓軟件的后端 API ,為安卓軟件程序提供數(shù)據(jù)服務(wù),而軟件本身只承擔(dān)界面和結(jié)構(gòu)的任務(wù),而數(shù)據(jù)則從后端 API 獲取。這個(gè)時(shí)候,發(fā)起的請(qǐng)求中, User-Agent 就會(huì)變成 Android 。
以上就是不能使用白名單策略的原因。
而黑名單在于簡(jiǎn)單,當(dāng)你希望屏蔽來(lái)自于 Python 代碼的請(qǐng)求或者來(lái)自于 Java 代碼的請(qǐng)求時(shí),只需要將其加入黑名單中即可。
通過(guò) Nginx 服務(wù)日志來(lái)查看請(qǐng)求頭中的 User-Agent
Nginx 是一款輕量級(jí)的 Web 服務(wù)器/反向代理服務(wù)器及電子郵件(IMAP/POP3)代理服務(wù)器。其特點(diǎn)是占有內(nèi)存少,并發(fā)能力強(qiáng),事實(shí)上 Nginx 的并發(fā)能力確實(shí)在同類型的網(wǎng)頁(yè)服務(wù)器中表現(xiàn)較好,使用 Nginx 企業(yè)有:百度、京東、新浪、網(wǎng)易、騰訊、淘寶等。
通常可以使用系統(tǒng)本身的安裝工具(Centos 的 yum、Debian 系的 apt-get 以及 MacOS 的 brew)安裝 Nginx,以 linux 系統(tǒng)為例,在終端中輸入:
sudo?apt-get?install?nginx
接下來(lái)根據(jù)提示選擇,即可完成 Nginx 的安裝。
接著在終端通過(guò)命令:
sudo?systemctl?start?nginx
即可啟動(dòng) Nginx 服務(wù)。
備注:由于各個(gè)系統(tǒng)差別以及版本差異,安裝和啟動(dòng)命令略有差別,解決辦法自行搜索
Nginx 為用戶提供了日志功能,其中記錄了每次服務(wù)器被請(qǐng)求的狀態(tài)和其他信息,包括 User-Agent。 Nginx 的默認(rèn)日志存放路徑為:
/var/log/nginx/
在終端通過(guò)命令
cd?/var/log/nginx?&&?ls
可以進(jìn)入到日志存放目錄并列出目錄下的文件,可以看到其中有兩個(gè)主要的文件,為?access.log?和?error.log
它們分別記錄著成功的請(qǐng)求信息和錯(cuò)誤信息。我們通過(guò) Nginx 的訪問(wèn)日志來(lái)查看每次請(qǐng)求的信息。
Nginx 啟動(dòng)后,默認(rèn)監(jiān)聽(tīng) 80 端口,你只需要訪問(wèn) IP 地址或者域名即可。假設(shè) IP 地址為?127.0.0.1,那么可以在瀏覽器輸入:
http://127.0.0.1
回車后,瀏覽器就會(huì)向服務(wù)器發(fā)起請(qǐng)求,和你平時(shí)上網(wǎng)是一樣的。
這里我們利用 Requests 庫(kù)來(lái)發(fā)起網(wǎng)絡(luò)請(qǐng)求。在本地新建一個(gè)名為?gets.py的文件,其中代碼為:
import?requests#?向目標(biāo)發(fā)起請(qǐng)求,并打印返回的?http?狀態(tài)碼resp?=?requests.get("http://127.0.0.1") print(resp.status_code)
Postman是一款功能強(qiáng)大的網(wǎng)頁(yè)調(diào)試與發(fā)送網(wǎng)頁(yè)HTTP請(qǐng)求的工具(Postman-),它可以模擬瀏覽器,訪問(wèn)指定的 Url 并輸出返回內(nèi)容,實(shí)際使用如下圖所示:
這是一個(gè)利用URL語(yǔ)法在命令行下工作的傳輸工具,它不僅支持 url 地址訪問(wèn)還支持文件上傳和下載,所以可以稱它為綜合傳輸工具。他也可以模擬瀏覽器,訪問(wèn)指定的 Url,實(shí)際使用如下圖所示:
上面使用了 4 種方法來(lái)向服務(wù)器發(fā)起請(qǐng)求,那么我們看看 Nginx 的日志中,記錄了什么樣的信息。在終端通過(guò)命令:
sudo?cat?access.log
來(lái)查看日志文件。可以看到這幾次的請(qǐng)求記錄:
#?請(qǐng)求記錄127.0.0.1?-?-?[04/Nov/2018:22:19:07?+0800]?"GET?/?HTTP/1.1"?200?396?"-"?"Mozilla/5.0?(X11;?Linux?x86_64)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/63.0.3239.132?Safari/537.36"127.0.0.1?-?-?[04/Nov/2018:22:19:07?+0800]?"GET?/favicon.ico?HTTP/1.1"?404?200?"http://127.0.0.1/"?"Mozilla/5.0?(X11;?Linux?x86_64)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/63.0.3239.132?Safari/537.36"127.0.0.1?-?-?[04/Nov/2018:22:20:36?+0800]?"GET?/?HTTP/1.1"?304?0?"-"?"Mozilla/5.0?(X11;?Linux?x86_64)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/63.0.3239.132?Safari/537.36"127.0.0.1?-?-?[04/Nov/2018:22:27:14?+0800]?"GET?/z_stat.php?id=1256772952&web_id=1256772952?HTTP/1.1"?404?144?"http://appstore.deepin.org/"?"Mozilla/5.0?(X11;?Linux?x86_64)?AppleWebKit/538.1?(KHTML,?like?Gecko)?deepin-appstore/4.0.9?Safari/538.1"127.0.0.1?-?-?[04/Nov/2018:22:42:10?+0800]?"GET?/?HTTP/1.1"?200?396?"-"?"PostmanRuntime/7.3.0"127.0.0.1?-?-?[04/Nov/2018:22:42:51?+0800]?"GET?/?HTTP/1.1"?200?612?"-"?"curl/7.60.0"
無(wú)論是 Python 還是 Curl 或者瀏覽器以及 Postman 的請(qǐng)求,都被記錄在日志文件中,說(shuō)明 Nginx 可以識(shí)別發(fā)起請(qǐng)求的終端類型。
之前的理論和邏輯,在實(shí)驗(yàn)中都得到了驗(yàn)證,那么接下來(lái)我們就通過(guò)黑名單策略將 Python 和 Curl 發(fā)起的請(qǐng)求過(guò)濾掉,只允許 Firefox 和 Postman 的請(qǐng)求通過(guò),并且對(duì)被過(guò)濾的請(qǐng)求返回 403 錯(cuò)誤提示。
反爬蟲的過(guò)程如上圖所示,相當(dāng)于在服務(wù)器和資源之間建立了一道防火墻,在黑名單中的請(qǐng)求將會(huì)被當(dāng)成垃圾丟棄掉。
Nginx 提供了配置文件以及對(duì)應(yīng)的規(guī)則,允許我們過(guò)濾掉不允許通過(guò)的請(qǐng)求,本次反爬蟲我們使用的就是它。Nginx 的配置文件通常放在/etc/nginx/目錄下,名為nginx.conf,我們通過(guò)查看配置文件來(lái)看一看,站點(diǎn)的配置文件在什么地方。再通過(guò)系統(tǒng)自帶的編輯器(筆者所用系統(tǒng)自帶 Nano,其他系統(tǒng)可能自帶 Vim)來(lái)編輯配置文件。在配置文件中找到站點(diǎn)配置文件地址(筆者所用電腦存放路徑為/etc/nginx/sites-enable),再到站點(diǎn)配置文件中找到local級(jí)別的配置,并在其中加上一下內(nèi)容:
if?($http_user_agent?~*?(Python|Curl))?{ ?????return?403; ????}
這段配置的釋義是判斷請(qǐng)求中請(qǐng)求頭字符串中是否包含有 Python或者 Curl,如果包含則直接返回 403 錯(cuò)誤,否則返回正常的資源。完成配置后保存,再通過(guò)命令:
sudo?nginx?-s?reload
整個(gè)操作過(guò)程如上圖所示,讓 Nginx 服務(wù)器重新載入配置文件,使得剛才的配置生效。
重復(fù)上面訪問(wèn)的步驟,通過(guò)瀏覽器、Python 代碼、Postman 工具和 Curl發(fā)起請(qǐng)求。從返回的結(jié)果就可以看到,與剛才是有所區(qū)別的。 * 瀏覽器返回的是正常的頁(yè)面,說(shuō)明沒(méi)有收到影響; * Python 代碼的狀態(tài)碼變成了 403,而不是之前的 200 * Postman 跟之前一樣,返回了正確的內(nèi)容; * Curl 跟 Python 一樣,無(wú)法正確的訪問(wèn)資源,因?yàn)樗鼈儼l(fā)起的請(qǐng)求都被過(guò)濾掉了。
提示:你可以繼續(xù)修改 Nginx 的配置來(lái)進(jìn)行測(cè)試,最終會(huì)發(fā)現(xiàn)結(jié)果會(huì)跟現(xiàn)在的一樣:只要在黑名單中,請(qǐng)求就會(huì)被過(guò)濾掉并且返回 403 錯(cuò)誤。
提示:這就是你平時(shí)編寫爬蟲代碼時(shí),需要在請(qǐng)求頭中偽造瀏覽器的原因。
通過(guò)上面的學(xué)習(xí),我們知道了 User-Agent 反爬蟲這種手段的原理,并且通過(guò) Nginx 來(lái)實(shí)現(xiàn)了反爬蟲,接下來(lái)我們一起學(xué)習(xí)如何繞過(guò)這種反爬蟲措施。
在 Requests 庫(kù)中,允許用戶自定義請(qǐng)求頭信息,所以我們可以在請(qǐng)求頭信息中將 User-Agent 的值改為瀏覽器的請(qǐng)求頭標(biāo)識(shí),這樣就能夠欺騙 Nginx 服務(wù)器,達(dá)到繞過(guò)反爬蟲的目的。將之前的 Python 代碼改為:
import?requests#?偽造請(qǐng)求頭信息?欺騙服務(wù)器headers?=?{"User-Agent":?"Mozilla/5.0?(Macintosh;?Intel?Mac?OS?X?10.13;?rv:9527.0)?Gecko/20100101?Firefox/9527.0"} resp?=?requests.get("http://127.0.0.1",?headers=headers) print(resp.status_code)
代碼中我們用到的是 Firefox 瀏覽器的請(qǐng)求頭信息,而且為了更好的觀察效果,我們可以更改瀏覽器的版本號(hào)(改成9527)以區(qū)分真實(shí)瀏覽器(這不會(huì)影響請(qǐng)求結(jié)果)。運(yùn)行這個(gè)文件,看看得到的返回結(jié)果:
200
不是 403 了,說(shuō)明已經(jīng)繞過(guò)了這種類型的反爬蟲(你看,這就是網(wǎng)上那些文章所寫的,需要修改請(qǐng)求頭信息才能繞過(guò)反爬蟲,現(xiàn)在你明白是怎么回事了吧)。
一個(gè)測(cè)試也許不準(zhǔn)確,你還可以通過(guò) Postman 再來(lái)測(cè)試一下,還記得怎么做嗎? * 將需要過(guò)濾的標(biāo)識(shí)(Postman)添加到 Nginx 的配置文件中 * 重載配置文件,使其生效 * 通過(guò) Postman 發(fā)起請(qǐng)求看看是否會(huì)被過(guò)濾 * 再次使用 Postman 工具,并且攜帶上瀏覽器的標(biāo)識(shí)再發(fā)起請(qǐng)求,看看是否會(huì)被過(guò)濾
小提示:這個(gè)練習(xí)如果你自己來(lái)做的話,會(huì)更容易理解其中的原理,并且可以加深你的映像。
總結(jié)
回顧一下,整篇文章的過(guò)程:
我們從遇到的反爬蟲現(xiàn)象開(kāi)始入手,接著學(xué)習(xí)了 User-Agent 這種反爬蟲策略的原理,并且通過(guò) Nginx 實(shí)現(xiàn)了反爬蟲,最后通過(guò) Python 代碼示例和 Postman 示例來(lái)驗(yàn)證我們的想法,最終清清楚楚、明明白白的了解到其中的緣由,待目標(biāo)改變了它的策略時(shí),我們也可以清楚的知道可以使用哪些方法來(lái)繞過(guò)。
思考:示例中,我僅僅是使用 Python 編寫爬蟲來(lái)演示,那么 Java 寫的爬蟲呢?PHP 編寫的爬蟲呢?安卓端發(fā)起的請(qǐng)求呢?
你可以依次測(cè)試,結(jié)果肯定讓你小有收獲。
如果你是一名爬蟲愛(ài)好者或者初級(jí)爬蟲工程師,同時(shí)你希望提升自己的水平,我們可以一起交流,掃碼關(guān)注吧!
在微信公眾號(hào)回復(fù)『反爬蟲報(bào)告』即可獲得下面這個(gè)反爬蟲結(jié)果報(bào)告文檔(PDF)
它會(huì)讓你看起來(lái)更專業(yè)
報(bào)告部分截圖:
本文轉(zhuǎn)載自異步社區(qū)
python
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。