1. 程式人生 > >常見表單反爬蟲安全措施解密

常見表單反爬蟲安全措施解密

許多像 Litmus 之類的測試工具已經用了很多年了,現在仍用於區分網路爬蟲和使用瀏覽器的人類訪問者,這類手段都取得了不同程度的效果。雖然網路機器人下載一些公開的文章和博文並不是什麼大事,但是如果網路機器人在你的網站上創造了幾千個賬號並開始向所有使用者傳送垃圾郵件,就是一個大問題了。網路表單,尤其是那些用於賬號建立和登入的網站,如果被機器人肆意地濫用,網站的安全和流量費用就會面臨嚴重威脅,因此努力限制網站的接入是最符合許多網站所有者的利益的(至少他們這麼認為)。

 

這些集中在表單和登入環節上的反機器人安全措施,對網路爬蟲來說確實是嚴重的挑戰。

 

4. 注意隱含輸入欄位值

 

在 HTML 表單中,“隱含”欄位可以讓欄位的值對瀏覽器可見,但是對使用者不可見(除非看網頁原始碼)。隨著越來越多的網站開始用 cookie 儲存狀態變數來管理使用者狀態,在找到另一個最佳用途之前,隱含欄位主要用於阻止爬蟲自動提交表單。

 

下圖顯示的例子就是 Facebook 登入頁面上的隱含欄位。雖然表單裡只有三個可見欄位(username、password 和一個確認按鈕),但是在原始碼裡表單會向伺服器傳送大量的資訊。

 

 

Facebook 登入頁面上的隱含欄位

 

用隱含欄位阻止網路資料採集的方式主要有兩種。第一種是表單頁面上的一個欄位可以用伺服器生成的隨機變量表示。如果提交時這個值不在表單處理頁面上,伺服器就有理由認為這個提交不是從原始表單頁面上提交的,而是由一個網路機器人直接提交到表單處理頁面的。繞開這個問題的最佳方法就是,首先採集表單所在頁面上生成的隨機變數,然後再提交到表單處理頁面。

 

第二種方式是“蜜罐”(honey pot)。如果表單裡包含一個具有普通名稱的隱含欄位(設定蜜罐圈套),比如“使用者名稱”(username)或“郵箱地址”(email address),設計不太好的網路機器人往往不管這個欄位是不是對使用者可見,直接填寫這個欄位並向伺服器提交,這樣就會中伺服器的蜜罐圈套。伺服器會把所有隱含欄位的真實值(或者與表單提交頁面的預設值不同的值)都忽略,而且填寫隱含欄位的訪問使用者也可能被網站封殺。

 

總之,有時檢查表單所在的頁面十分必要,看看有沒有遺漏或弄錯一些伺服器預先設定好的隱含欄位(蜜罐圈套)。如果你看到一些隱含欄位,通常帶有較大的隨機字串變數,那麼很可能網路伺服器會在表單提交的時候檢查它們。另外,還有其他一些檢查,用來保證這些當前生成的表單變數只被使用一次或是最近生成的(這樣可以避免變數被簡單地儲存到一個程式中反覆使用)。

 

5. 爬蟲通常如何避開蜜罐

 

雖然在進行網路資料採集時用 CSS 屬性區分有用資訊和無用資訊會很容易(比如,通過讀取 id和 class 標籤獲取資訊),但這麼做有時也會出問題。如果網路表單的一個欄位通過 CSS 設定成對使用者不可見,那麼可以認為普通使用者訪問網站的時候不能填寫這個欄位,因為它沒有顯示在瀏覽器上。如果這個欄位被填寫了,就可能是機器人乾的,因此這個提交會失效。

 

這種手段不僅可以應用在網站的表單上,還可以應用在連結、圖片、檔案,以及一些可以被機器人讀取,但普通使用者在瀏覽器上卻看不到的任何內容上面。訪問者如果訪問了網站上的一個“隱含”內容,就會觸發伺服器指令碼封殺這個使用者的 IP 地址,把這個使用者踢出網站,或者採取其他措施禁止這個使用者接入網站。實際上,許多商業模式就是在幹這些事情。

 

下面的例子所用的網頁在 http://pythonscraping.com/pages/itsatrap.html。這個頁面包含了兩個連結,一個通過 CSS 隱含了,另一個是可見的。另外,頁面上還包括兩個隱含欄位:

 


點選可檢視大圖

 

這三個元素通過三種不同的方式對使用者隱藏:

  • 第一個連結是通過簡單的 CSS 屬性設定 display:none 進行隱藏

  • 電話號碼欄位 name="phone" 是一個隱含的輸入欄位

  • 郵箱地址欄位 name="email" 是將元素向右移動 50 000 畫素(應該會超出電腦顯示器的邊界)並隱藏滾動條

 

因為 Selenium 可以獲取訪問頁面的內容,所以它可以區分頁面上的可見元素與隱含元素。通過 is_displayed() 可以判斷元素在頁面上是否可見。

 

例如,下面的程式碼示例就是獲取前面那個頁面的內容,然後查詢隱含連結和隱含輸入欄位:

 

點選可檢視大圖

 

Selenium 抓取出了每個隱含的連結和欄位,結果如下所示:

 

點選可檢視大圖

 

雖然你不太可能會去訪問你找到的那些隱含連結,但是在提交前,記得確認一下那些已經在表單中、準備提交的隱含欄位的值(或者讓 Selenium 為你自動提交)。

 

使用遠端伺服器來避免 IP 封鎖

 

啟用遠端平臺的人通常有兩個目的:對更大計算能力和靈活性的需求,以及對可變 IP 地址的需求

 

6. 使用可變的遠端 IP 地址

 

建立網路爬蟲的第一原則是:所有資訊都可以偽造。你可以用非本人的郵箱傳送郵件,通過命令列自動化滑鼠的行為,或者通過 IE 5.0 瀏覽器耗費網站流量來嚇唬網管。

 

但是有一件事情是不能作假的,那就是你的 IP 地址。任何人都可以用這個地址給你寫信:“美國華盛頓特區賓夕法尼亞大道西北 1600 號,總統,郵編 20500。”但是,如果這封信是從新墨西哥州的阿爾伯克基市發來的,那麼你肯定可以確信給你寫信的不是美國總統。

 

從技術上說,IP 地址是可以通過傳送資料包進行偽裝的,就是分散式拒絕服務攻擊技術(Distributed Denial of Service,DDoS),攻擊者不需要關心接收的資料包(這樣傳送請求的時候就可以使用假 IP 地址)。但是網路資料採集是一種需要關心伺服器響應的行為,所以我們認為 IP 地址是不能造假的。

 

阻止網站被採集的注意力主要集中在識別人類與機器人的行為差異上面。封殺 IP 地址這種矯枉過正的行為,就好像是農民不靠噴農藥給莊稼殺蟲,而是直接用火燒徹底解決問題。它是最後一步棋,不過是一種非常有效的方法,只要忽略危險 IP 地址發來的資料包就可以了。但是,使用這種方法會遇到以下幾個問題。

 

  • IP 地址訪問列表很難維護。雖然大多數大型網站都會用自己的程式自動管理 IP 地址訪問列表(機器人封殺機器人),但是至少需要人偶爾檢查一下列表,或者至少要監控問題的增長。

  • 因為伺服器需要根據 IP 地址訪問列表去檢查每個準備接收的資料包,所以檢查接收資料包時會額外增加一些處理時間。多個 IP 地址乘以海量的資料包更會使檢查時間指數級增長。為了降低處理時間和處理複雜度,管理員通常會對 IP 地址進行分組管理並制定相應的規則,比如如果這組 IP 中有一些危險分子就“把這個區間的所有 256 個地址全部封殺”。於是產生了下一個問題。

  • 封殺 IP 地址可能會導致意外後果。例如,當我還在美國麻省歐林工程學院讀本科的時候,有個同學寫了一個可以在 http://digg.com/ 網站(在 Reddit 流行之前大家都用 Digg)上對熱門內容進行投票的軟體。這個軟體的伺服器 IP 地址被 Digg 封殺,導致整個網站都不能訪問。於是這個同學就把軟體移到了另一個伺服器上,而 Digg 自己卻失去了許多主要目標使用者的訪問量。

 

雖然有這些缺點,但封殺 IP 地址依然是一種十分常用的手段,伺服器管理員用它來阻止可疑的網路爬蟲入侵伺服器。

 

Tor 代理伺服器

 

洋蔥路由(The Onion Router)網路,常用縮寫為 Tor,是一種 IP 地址匿名手段。由網路志願者伺服器構建的洋蔥路由器網路,通過不同伺服器構成多個層(就像洋蔥)把客戶端包在最裡面。資料進入網路之前會被加密,因此任何伺服器都不能偷取通訊資料。另外,雖然每一個伺服器的入站和出站通訊都可以被查到,但是要想查出通訊的真正起點和終點,必須知道整個通訊鏈路上所有伺服器的入站和出站通訊細節,而這基本是不可能實現的。

 

 Tor 匿名的侷限性

雖然我們在本文中用 Tor 的目的是改變 IP 地址,而不是實現完全匿名,但有必要關注一下 Tor 匿名方法的能力和不足。

 

雖然 Tor 網路可以讓你訪問網站時顯示的 IP 地址是一個不能跟蹤到你的 IP 地址,但是你在網站上留給伺服器的任何資訊都會暴露你的身份。例如,你登入 Gmail 賬號後再用 Google 搜尋,那些搜尋歷史就會和你的身份繫結在一起。

 

另外,登入 Tor 的行為也可能讓你的匿名狀態處於危險之中。2013 年 12 月,一個哈佛大學本科生想逃避期末考試,就用一個匿名郵箱賬號通過 Tor 網路給學校發了一封炸彈威脅信。結果哈佛大學的 IT 部門通過日誌查到,在炸彈威脅信發來的時候,Tor 網路的流量只來自一臺機器,而且是一個在校學生註冊的。雖然他們不能確定流量的最初源頭(只知道是通過 Tor 傳送的),但是作案時間和註冊資訊證據充分,而且那個時間段內只有一臺機器是登入狀態,這就有充分理由起訴那個學生了。

 

登入 Tor 網路不是一個自動的匿名措施,也不能讓你進入網際網路上任何區域。雖然它是一個實用的工具,但是用它的時候一定要謹慎、清醒,並且遵守道德規範。

 

在 Python 裡使用 Tor,需要先安裝執行 Tor,下一節將介紹。Tor 服務很容易安裝和開啟。只要去 Tor 下載頁面下載並安裝,開啟後連線就可以。不過要注意,當你用 Tor 的時候網速會變慢。這是因為代理有可能要先在全世界網路上轉幾次才到目的地!

 

PySocks

 

PySocks 是一個非常簡單的 Python 代理伺服器通訊模組,它可以和 Tor 配合使用。你可以從它的網站(https://pypi.python.org/pypi/PySocks)上下載,或者使用任何第三方模組管理器安裝。

 

這個模組的用法很簡單。示例程式碼如下所示。執行的時候,Tor 服務必須執行在 9150 埠(預設值)上:

 

 

網站 http://icanhazip.com/ 會顯示客戶端連線的網站伺服器的 IP 地址,可以用來測試 Tor 是否正常執行。當程式執行之後,顯示的 IP 地址就不是你原來的 IP 了。

 

如果你想在 Tor 裡面用 Selenium 和 PhantomJS,不需要 PySocks,只要保證 Tor 在執行,然後增加 service_args 引數設定代理埠,讓 Selenium 通過埠 9150 連線網站就可以了:

 

和之前一樣,這個程式列印的 IP 地址也不是你原來的,而是你通過 Tor 客戶端獲得的 IP 地址。

 

從網站主機執行

 

如果你擁有個人網站或公司網站,那麼你可能已經知道如何使用外部伺服器執行你的網路爬蟲了。即使是一些相對封閉的網路伺服器,沒有可用的命令列接入方式,你也可以通過網頁介面對程式進行控制。

 

如果你的網站部署在 Linux 伺服器上,應該已經運行了 Python。如果你用的是 Windows 伺服器,可能就沒那麼幸運了;你需要仔細檢查一下 Python 有沒有安裝,或者問問網管可不可以安裝。

 

大多數小型網路主機都會提供一個軟體叫 cPanel,提供網站管理和後臺服務的基本管理功能和資訊。如果你接入了 cPanel,就可以設定 Python 在伺服器上執行——進入“Apache Handlers”然後增加一個 handler(如還沒有的話):

 

 

這會告訴伺服器所有的 Python 指令碼都將作為一個 CGI 指令碼執行。CGI 就是通用閘道器介面(Common Gateway Interface),是可以在伺服器上執行的任何程式,會動態地生成內容並顯示在網站上。把 Python 指令碼顯式地定義成 CGI 指令碼,就是給伺服器許可權去執行 Python 指令碼,而不只是在瀏覽器上顯示它們或者讓使用者下載它們。

 

寫完 Python 指令碼後上傳到伺服器,然後把檔案許可權設定成 755,讓它可執行。通過瀏覽器找到程式上傳的位置(也可以寫一個爬蟲來自動做這件事情)就可以執行程式。如果你擔心在公共領域執行指令碼不安全,可以採取以下兩種方法。

 

  • 把指令碼儲存在一個隱晦或深層的 URL 裡,確保其他 URL 連結都不能接入這個指令碼,這樣可以避免搜尋引擎發現它。

  • 用密碼保護指令碼,或者在執行指令碼之前用密碼或加密令牌進行確認。

 

確實,通過這些原本主要是用來顯示網站的服務執行 Python 指令碼有點兒複雜。比如,你可能會發現網路爬蟲執行時網站的載入速度變慢了。其實,在整個採集任務完成之前頁面都是不會載入的(得等到所有“print”語句的輸出內容都顯示完)。這可能會消耗幾分鐘,幾小時,甚至永遠也完成不了,要看程式的具體情況了。雖然它最終一定能完成任務,但是可能你還想看到實時的結果,這樣就需要一臺真正的伺服器了。

 

從雲主機執行

 

雖然雲端計算的花費可能是無底洞,但是寫這篇文章時,啟動一個計算例項最便宜只要每小時 1.3 美分(亞馬遜 EC2 的 micro 例項,其他例項會更貴),Google 最便宜的計算例項是每小時 4.5 美分,最少需要用 10 分鐘。考慮計算能力的規模效應,從大公司買一個小型的雲端計算例項的費用,和自己買一臺專業實體機的費用應該差不多——不過用雲端計算不需要僱人去維護裝置。

 

設定好計算例項之後,你就有了新 IP 地址、使用者名稱,以及可以通過 SSH 進行例項連線的公私金鑰了。後面要做的每件事情,都應該和你在實體伺服器上乾的事情一樣了——當然,你不需要再擔心硬體維護,也不用運行復雜多餘的監控工具了。

 

總結

爬蟲被封禁常見原因列表

 

如果你一直被網站封殺卻找不到原因,那麼這裡有個檢查列表,可以幫你診斷一下問題出在哪裡。

 

    • 首先,檢查 JavaScript 。如果你從網路伺服器收到的頁面是空白的,缺少資訊,或其遇到他不符合你預期的情況(或者不是你在瀏覽器上看到的內容),有可能是因為網站建立頁面的 JavaScript 執行有問題

    • 檢查正常瀏覽器提交的引數。如果你準備向網站提交表單或發出 POST 請求,記得檢查一下頁面的內容,看看你想提交的每個欄位是不是都已經填好,而且格式也正確。用 Chrome 瀏覽器的網路面板(快捷鍵 F12 開啟開發者控制檯,然後點選“Network”即可看到)檢視傳送到網站的 POST 命令,確認你的每個引數都是正確的。

    • 是否有合法的 Cookie?如果你已經登入網站卻不能保持登入狀態,或者網站上出現了其他的“登入狀態”異常,請檢查你的 cookie。確認在載入每個頁面時 cookie 都被正確呼叫,而且你的 cookie 在每次發起請求時都發送到了網站上。

    • IP 被封禁?如果你在客戶端遇到了 HTTP 錯誤,尤其是 403 禁止訪問錯誤,這可能說明網站已經把你的 IP 當作機器人了,不再接受你的任何請求。你要麼等待你的 IP 地址從網站黑名單裡移除,要麼就換個 IP 地址(可以去星巴克上網)。如果你確定自己並沒有被封殺,那麼再檢查下面的內容。

      • 確認你的爬蟲在網站上的速度不是特別快。快速採集是一種惡習,會對網管的伺服器造成沉重的負擔,還會讓你陷入違法境地,也是 IP 被網站列入黑名單的首要原因。給你的爬蟲增加延遲,讓它們在夜深人靜的時候執行。切記:匆匆忙忙寫程式或收集資料都是拙劣專案管理的表現;應該提前做好計劃,避免臨陣慌亂。

      • 還有一件必須做的事情:修改你的請求頭!有些網站會封殺任何聲稱自己是爬蟲的訪問者。如果你不確定請求頭的值怎樣才算合適,就用你自己瀏覽器的請求頭吧。

      • 確認你沒有點選或訪問任何人類使用者通常不能點選或接入的資訊。

      • 如果你用了一大堆複雜的手段才接入網站,考慮聯絡一下網管吧,告訴他們你的目的。試試發郵件到 [email protected]< 域名 > 或 [email protected]< 域名 >,請求網管允許你使用爬蟲採集資料。管理員也是人嘛!