許多像 Litmus 之類的測試工具已經用了不少年了,如今仍用於區分網絡爬蟲和使用瀏覽器的人類訪問者,這類手段都取得了不一樣程度的效果。雖然網絡機器人下載一些公開的文章和博文並非什麼大事,可是若是網絡機器人在你的網站上創造了幾千個帳號並開始向全部用戶發送垃圾郵件,就是一個大問題了。網絡表單,尤爲是那些用於帳號建立和登陸的網站,若是被機器人肆意地濫用,網站的安全和流量費用就會面臨嚴重威脅,所以努力限制網站的接入是最符合許多網站全部者的利益的(至少他們這麼認爲)。html
這些集中在表單和登陸環節上的反機器人安全措施,對網絡爬蟲來講確實是嚴重的挑戰。python
在 HTML 表單中,「隱含」字段可讓字段的值對瀏覽器可見,可是對用戶不可見(除非看網頁源代碼)。隨着愈來愈多的網站開始用 cookie 存儲狀態變量來管理用戶狀態,在找到另外一個最佳用途以前,隱含字段主要用於阻止爬蟲自動提交表單。web
下圖顯示的例子就是 Facebook 登陸頁面上的隱含字段。雖然表單裏只有三個可見字段(username、password 和一個確認按鈕),可是在源代碼裏表單會向服務器傳送大量的信息。api
Facebook 登陸頁面上的隱含字段瀏覽器
用隱含字段阻止網絡數據採集的方式主要有兩種。第一種是表單頁面上的一個字段能夠用服務器生成的隨機變量表示。若是提交時這個值不在表單處理頁面上,服務器就有理由認爲這個提交不是從原始表單頁面上提交的,而是由一個網絡機器人直接提交到表單處理頁面的。繞開這個問題的最佳方法就是,首先採集表單所在頁面上生成的隨機變量,而後再提交到表單處理頁面。安全
第二種方式是「蜜罐」(honey pot)。若是表單裏包含一個具備普通名稱的隱含字段(設置蜜罐圈套),好比「用戶名」(username)或「郵箱地址」(email address),設計不太好的網絡機器人每每無論這個字段是否是對用戶可見,直接填寫這個字段並向服務器提交,這樣就會中服務器的蜜罐圈套。服務器會把全部隱含字段的真實值(或者與表單提交頁面的默認值不一樣的值)都忽略,並且填寫隱含字段的訪問用戶也可能被網站封殺。服務器
總之,有時檢查表單所在的頁面十分必要,看看有沒有遺漏或弄錯一些服務器預先設定好的隱含字段(蜜罐圈套)。若是你看到一些隱含字段,一般帶有較大的隨機字符串變量,那麼極可能網絡服務器會在表單提交的時候檢查它們。另外,還有其餘一些檢查,用來保證這些當前生成的表單變量只被使用一次或是最近生成的(這樣能夠避免變量被簡單地存儲到一個程序中反覆使用)。cookie
雖然在進行網絡數據採集時用 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 地址的需求。
創建網絡爬蟲的第一原則是:全部信息均可以僞造。你能夠用非本人的郵箱發送郵件,經過命令行自動化鼠標的行爲,或者經過 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 地址依然是一種十分經常使用的手段,服務器管理員用它來阻止可疑的網絡爬蟲入侵服務器。
洋蔥路由(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 是一個很是簡單的 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 被網站列入黑名單的首要緣由。給你的爬蟲增長延遲,讓它們在夜深人靜的時候運行。切記:匆匆忙忙寫程序或收集數據都是拙劣項目管理的表現;應該提早作好計劃,避免臨陣慌亂。
還有一件必須作的事情:修改你的請求頭!有些網站會封殺任何聲稱本身是爬蟲的訪問者。若是你不肯定請求頭的值怎樣纔算合適,就用你本身瀏覽器的請求頭吧。
確認你沒有點擊或訪問任何人類用戶一般不能點擊或接入的信息。
若是你用了一大堆複雜的手段才接入網站,考慮聯繫一下網管吧,告訴他們你的目的。試試發郵件到 webmaster@< 域名 > 或 admin@< 域名 >,請求網管容許你使用爬蟲採集數據。管理員也是人嘛!