隨著 Python 和大數(shù)據(jù)的火熱,大量的工程師蜂擁而上,爬蟲技術由于易學、效果顯著首當其沖的成為了大家追捧的對象,爬蟲的發(fā)展進入了高峰期,因此給服務器帶來的壓力則是成倍的增加。企業(yè)或為了保證服務的正常運轉(zhuǎn)或為了降低壓力與成本,不得不使出各種各樣的技術手段來阻止爬蟲工程師們毫無節(jié)制的向服務器索取資源,我們將這種行為稱為『反爬蟲』。
『反爬蟲技術』是互聯(lián)網(wǎng)技術中為了限制爬蟲而產(chǎn)生的技術總稱,而反爬蟲的繞過則是所有爬蟲工程師要面對的問題,也是中高級爬蟲工程師面試中最關注的方面。
問題所在
但是在平時的交流中,筆者發(fā)現(xiàn)大多數(shù)的初級爬蟲工程師只會拿著網(wǎng)上別人寫的技術文章唾沫橫飛,除了知道在請求的時候偽造瀏覽器請求頭信息中的 User-Agent 以外,對于:
- 為什么要這么做?
- 這么做有什么好處?
- 我可以用別的方法實現(xiàn)么?
- 它的原理是怎么樣的?
- 它是如何識別我的爬蟲的?
- 我應該用什么方式繞過它?
一無所知。如果你既不知道原理又不知道實現(xiàn)方式,那么當目標網(wǎng)站稍微調(diào)整一下反爬蟲策略的時候,你還是一臉懵逼
對,就是一臉懵逼。
作者心聲
我也在嘗試著,能夠?qū)⑦@樣的知識分享出來,讓大家在閑暇之余能夠通過這篇文章學習到反爬蟲知識中比較簡單的反爬蟲原理和實現(xiàn)方法,再熟悉他的繞過操作。比如 User-Agent 反爬手段,了解它的原理并且親手實現(xiàn)反爬蟲,再親手繞過它?;蛟S通過這個小小的案例,就可以打開你思維的大門、撬開你思路的下水道。
正文
上面是空談,下面是實踐。一位偉人曾經(jīng)表達過這么一個意思:
管你黑貓白貓,抓不到老鼠的貓,它就不是個好貓
什么是 User-Agent
User Agent中文名為用戶代理,簡稱 UA,它是一個特殊字符串頭,使得服務器能夠識別客戶使用的操作系統(tǒng)及版本、CPU 類型、瀏覽器及版本、瀏覽器渲染引擎、瀏覽器語言、瀏覽器插件等。一些網(wǎng)站常常通過判斷 UA 來給不同的操作系統(tǒng)、不同的瀏覽器發(fā)送不同的頁面,因此可能造成某些頁面無法在某個瀏覽器中正常顯示,但通過偽裝 UA 可以繞過檢測。瀏覽器向服務器發(fā)起請求的流程圖,可以用下圖表示:
這里以火狐瀏覽器和谷歌瀏覽器為例,UA 的格式或者說表現(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)絡請求中充當什么角色?
在網(wǎng)絡請求當中,User-Agent 是標明身份的一種標識,服務器可以通過請求頭參數(shù)中的 User-Agent 來判斷請求方是否是瀏覽器、客戶端程序或者其他的終端(當然,User-Agent 的值為空也是允許的,因為它不是必要參數(shù))。
瀏覽器的角色,如上圖方框中所示,那么 User-Agent 的角色,就是表明身份。
為什么反爬蟲會選擇 User-Agent 這個參數(shù)呢?
從上面的介紹中,可以看出它是終端的身份標識。意味著服務器可以清楚的知道,這一次的請求是通過火狐瀏覽器發(fā)起的,還是通過 IE 瀏覽器發(fā)起的,甚至說是否是應用程序(比如 Python )發(fā)起的。
網(wǎng)站的頁面、動效和圖片等內(nèi)容的呈現(xiàn)是借助于瀏覽器的渲染功能實現(xiàn)的,瀏覽器是一個相對封閉的程序,因為它要確保數(shù)據(jù)的成功渲染,所以用戶無法從瀏覽器中大規(guī)模的、自動化的獲取內(nèi)容數(shù)據(jù)。
而爬蟲卻不是這樣的,爬蟲生來就是為了獲取網(wǎng)絡上的內(nèi)容并將其轉(zhuǎn)化為數(shù)據(jù)。這是兩種截然不同的方式,你也可以理解為通過編寫代碼來大規(guī)模的、自動化的獲取內(nèi)容數(shù)據(jù),這是一種騷操作。
回到正題,為什么會選擇 User-Agent 這個參數(shù)呢?
因為編程語言都有默認的標識,在發(fā)起網(wǎng)絡請求的時候,這個標識在你毫不知情的情況下,作為請求頭參數(shù)中的 User-Agent 值一并發(fā)送到服務器。比如 Python 語言通過代碼發(fā)起網(wǎng)絡請求時, User-Agent 的值中就包含 Python 。同樣的,Java 和 PHP 這些語言也都有默認的標識。
反爬蟲的黑名單策略
既然知道編程語言的這個特點,再結(jié)合實際的需求,那么反爬蟲的思路就出來了。這是一中黑名單策略,只要出現(xiàn)在黑名單中的請求,都視為爬蟲,對于此類請求可以不予處理或者返回相應的錯誤提示。
為什么用黑名單策略不用白名單策略?
現(xiàn)實生活中,瀏覽器類型繁多(火狐瀏覽器、谷歌瀏覽器、360 瀏覽器、傲游瀏覽器、歐普拉瀏覽器、世界之窗瀏覽器、QQ 瀏覽器等),
想要將所有的瀏覽器品牌、類型以及對應的標識收集并放到名單中,那是不實際的,假如漏掉了哪一種,那么對網(wǎng)站來說是一種損失。
再者說來,很多的服務并不僅僅開放給瀏覽器,有些時候這些服務以 API 的形式向應用程序提供服務,比如安卓軟件的后端 API ,為安卓軟件程序提供數(shù)據(jù)服務,而軟件本身只承擔界面和結(jié)構(gòu)的任務,而數(shù)據(jù)則從后端 API 獲取。這個時候,發(fā)起的請求中, User-Agent 就會變成 Android 。
以上就是不能使用白名單策略的原因。
而黑名單在于簡單,當你希望屏蔽來自于 Python 代碼的請求或者來自于 Java 代碼的請求時,只需要將其加入黑名單中即可。
通過 Nginx 服務日志來查看請求頭中的 User-Agent
Nginx 是一款輕量級的 Web 服務器/反向代理服務器及電子郵件(IMAP/POP3)代理服務器。其特點是占有內(nèi)存少,并發(fā)能力強,事實上 Nginx 的并發(fā)能力確實在同類型的網(wǎng)頁服務器中表現(xiàn)較好,使用 Nginx 企業(yè)有:百度、京東、新浪、網(wǎng)易、騰訊、淘寶等。
Nginx 的安裝與啟動
通常可以使用系統(tǒng)本身的安裝工具(Centos 的 yum、Debian 系的 apt-get 以及 MacOS 的 brew)安裝 Nginx,以 linux 系統(tǒng)為例,在終端中輸入:
sudo apt-get install nginx
接下來根據(jù)提示選擇,即可完成 Nginx 的安裝。
接著在終端通過命令:
sudo systemctl start nginx
即可啟動 Nginx 服務。
備注:由于各個系統(tǒng)差別以及版本差異,安裝和啟動命令略有差別,解決辦法自行搜索
Nginx 的日志
Nginx 為用戶提供了日志功能,其中記錄了每次服務器被請求的狀態(tài)和其他信息,包括 User-Agent。 Nginx 的默認日志存放路徑為:
/var/log/nginx/
在終端通過命令
cd /var/log/nginx && ls
可以進入到日志存放目錄并列出目錄下的文件,可以看到其中有兩個主要的文件,為 access.log 和 error.log
它們分別記錄著成功的請求信息和錯誤信息。我們通過 Nginx 的訪問日志來查看每次請求的信息。
發(fā)起請求的幾種辦法
瀏覽器
Nginx 啟動后,默認監(jiān)聽 80 端口,你只需要訪問 IP 地址或者域名即可。假設 IP 地址為 127.0.0.1,那么可以在瀏覽器輸入:
http://127.0.0.1
回車后,瀏覽器就會向服務器發(fā)起請求,和你平時上網(wǎng)是一樣的。
Postman
Postman是一款功能強大的網(wǎng)頁調(diào)試與發(fā)送網(wǎng)頁HTTP請求的工具(Postman下載地址),它可以模擬瀏覽器,訪問指定的 Url 并輸出返回內(nèi)容,實際使用如下圖所示:
Curl
這是一個利用URL語法在命令行下工作的傳輸工具,它不僅支持 url 地址訪問還支持文件上傳和下載,所以可以稱它為綜合傳輸工具。他也可以模擬瀏覽器,訪問指定的 Url,實際使用如下圖所示:
Nginx 日志記錄結(jié)果
上面使用了 4 種方法來向服務器發(fā)起請求,那么我們看看 Nginx 的日志中,記錄了什么樣的信息。在終端通過命令:
sudo cat access.log
來查看日志文件??梢钥吹竭@幾次的請求記錄:
無論是 Python 還是 Curl 或者瀏覽器以及 Postman 的請求,都被記錄在日志文件中,說明 Nginx 可以識別發(fā)起請求的終端類型。
實現(xiàn)反爬蟲
之前的理論和邏輯,在實驗中都得到了驗證,那么接下來我們就通過黑名單策略將 Python 和 Curl 發(fā)起的請求過濾掉,只允許 Firefox 和 Postman 的請求通過,并且對被過濾的請求返回 403 錯誤提示。
反爬蟲的過程如上圖所示,相當于在服務器和資源之間建立了一道防火墻,在黑名單中的請求將會被當成垃圾丟棄掉。
配置 Nginx 規(guī)則
Nginx 提供了配置文件以及對應的規(guī)則,允許我們過濾掉不允許通過的請求,本次反爬蟲我們使用的就是它。Nginx 的配置文件通常放在/etc/nginx/目錄下,名為nginx.conf,我們通過查看配置文件來看一看,站點的配置文件在什么地方。再通過系統(tǒng)自帶的編輯器(筆者所用系統(tǒng)自帶 Nano,其他系統(tǒng)可能自帶 Vim)來編輯配置文件。在配置文件中找到站點配置文件地址(筆者所用電腦存放路徑為/etc/nginx/sites-enable),再到站點配置文件中找到local級別的配置,并在其中加上一下內(nèi)容:
if ($http_user_agent ~* (Python|Curl)) {
return 403;
}
這段配置的釋義是判斷請求中請求頭字符串中是否包含有 Python或者 Curl,如果包含則直接返回 403 錯誤,否則返回正常的資源。完成配置后保存,再通過命令:
sudo nginx -s reload
整個操作過程如上圖所示,讓 Nginx 服務器重新載入配置文件,使得剛才的配置生效。
反爬蟲效果測試
重復上面訪問的步驟,通過瀏覽器、Python 代碼、Postman 工具和 Curl發(fā)起請求。從返回的結(jié)果就可以看到,與剛才是有所區(qū)別的。
- 瀏覽器返回的是正常的頁面,說明沒有收到影響;
- Python 代碼的狀態(tài)碼變成了 403,而不是之前的 200
- Postman 跟之前一樣,返回了正確的內(nèi)容;
- Curl 跟 Python 一樣,無法正確的訪問資源,因為它們發(fā)起的請求都被過濾掉了。
提示:你可以繼續(xù)修改 Nginx 的配置來進行測試,最終會發(fā)現(xiàn)結(jié)果會跟現(xiàn)在的一樣:只要在黑名單中,請求就會被過濾掉并且返回 403 錯誤。
提示:這就是你平時編寫爬蟲代碼時,需要在請求頭中偽造瀏覽器的原因。
繞過 User-Agent 方式的反爬蟲
通過上面的學習,我們知道了 User-Agent 反爬蟲這種手段的原理,并且通過 Nginx 來實現(xiàn)了反爬蟲,接下來我們一起學習如何繞過這種反爬蟲措施。
Python 繞過反爬蟲
在 Requests 庫中,允許用戶自定義請求頭信息,所以我們可以在請求頭信息中將 User-Agent 的值改為瀏覽器的請求頭標識,這樣就能夠欺騙 Nginx 服務器,達到繞過反爬蟲的目的。將之前的 Python 代碼改為:
代碼中我們用到的是 Firefox 瀏覽器的請求頭信息,而且為了更好的觀察效果,我們可以更改瀏覽器的版本號(改成9527)以區(qū)分真實瀏覽器(這不會影響請求結(jié)果)。運行這個文件,看看得到的返回結(jié)果:
200
不是 403 了,說明已經(jīng)繞過了這種類型的反爬蟲(你看,這就是網(wǎng)上那些文章所寫的,需要修改請求頭信息才能繞過反爬蟲,現(xiàn)在你明白是怎么回事了吧)。
練習:使用 Postman 再測試一下
一個測試也許不準確,你還可以通過 Postman 再來測試一下,還記得怎么做嗎?
- 將需要過濾的標識(Postman)添加到 Nginx 的配置文件中
- 重載配置文件,使其生效
- 通過 Postman 發(fā)起請求看看是否會被過濾
- 再次使用 Postman 工具,并且攜帶上瀏覽器的標識再發(fā)起請求,看看是否會被過濾
小提示:這個練習如果你自己來做的話,會更容易理解其中的原理,并且可以加深你的映像。
總結(jié)
回顧一下,整篇文章的過程:
我們從遇到的反爬蟲現(xiàn)象開始入手,接著學習了 User-Agent 這種反爬蟲策略的原理,并且通過 Nginx 實現(xiàn)了反爬蟲,最后通過 Python 代碼示例和 Postman 示例來驗證我們的想法,最終清清楚楚、明明白白的了解到其中的緣由,待目標改變了它的策略時,我們也可以清楚的知道可以使用哪些方法來繞過。
作者:韋世東、 轉(zhuǎn)自:進擊的Coder