我是一個Web Crawler , 你們經(jīng)常說的爬蟲!
誕生
我是一個Web Crawler , 有時候稱為Spider , 你們經(jīng)常說的爬蟲就是我。
我想我是遇到了好時代,感謝IT政府,提供了簡單的HTTP協(xié)議,還有HTML,CSS, JavaScript這一系列開放的技術, 原來的桌面應用,局域網(wǎng)應用都被搬到了網(wǎng)絡上,形成了一個個的網(wǎng)站, 網(wǎng)站互聯(lián)起來,形成了一個覆蓋全世界的大網(wǎng)。
在這個大背景下,我應運而生,開始在這個大網(wǎng)上爬來爬去,收集、分析各種網(wǎng)頁的數(shù)據(jù)。
我有幾個親戚在搜索引擎公司工作,聽說他們的目標是把全世界的網(wǎng)頁都給爬下來,形成索引,讓人類搜索, 想想全世界網(wǎng)頁的數(shù)量,這幾位親戚的工作實在是讓人敬畏。
我的工作原理非常簡單, 給我一個URL,我就可以通過HTTP協(xié)議把HTML頁面下載下來。然后分析一下這個頁面中有哪些元素,比如說,表單,表格,鏈接等等。
反正這個HTML頁面是純文本的,我想怎么折騰都可以,我可以把它形成一顆DOM樹,也可以用正則表達式去獲得一段我想要的內容,總之方法多得很呢!
最重要的是,我要拿到這個頁面中的其他鏈接, 然后再拿到這些鏈接對應的HTML頁面,繼續(xù)我的分析,如此循環(huán)下去,就能把所有的頁面給找出來了,所有的內容都盡在掌握!
有時候,有些HTML頁面是受到保護的,必須登陸以后才能夠訪問,這也難不住我,人類早已經(jīng)申請了很多的賬號。我把這些用戶名和密碼拿過來,找到對應的登錄框,向服務器端發(fā)送一個請求,就可以順利登錄了, 訪問受保護網(wǎng)頁的大門就敞開了。
所以說我有兩個最基本的能力, 第一,通過HTTP協(xié)議訪問網(wǎng)頁; 第二,分析HTML網(wǎng)頁。
斗爭
所謂“爬亦有道”, 我們爬蟲界也是有一定規(guī)范的,比如說,你在你的網(wǎng)站的根目錄下放一個robots.txt文件,里邊定義好那些內容對爬蟲開放,那些內容不希望爬蟲訪問, 那我們就不會去爬這些內容了。
當然這只是個約定俗成的規(guī)范,而不是標準, 所以總是有一些爬蟲完全不遵守規(guī)則,置這些規(guī)范于不顧。
作為程序,我們訪問起網(wǎng)絡來, 要遠遠比人類快得多,人類還需要在界面上移動鼠標點擊,我們則是拿到URL后直接、迅速、毫不猶豫地訪問, 這樣一來,如果爬蟲很多,常常給一些網(wǎng)站帶來非常大的流量,給服務器帶來很大的壓力,影響了正常用戶的訪問, 從而影響了網(wǎng)站的收入。
斷人財路,網(wǎng)站就急眼了, 肯定要反擊, 于是他們網(wǎng)站便提出了各種各樣的辦法,成為反爬蟲。 他們有反爬蟲, 我們便反反爬蟲,于是便引發(fā)了一場波瀾壯闊,反復拉鋸的戰(zhàn)爭。
首先他們得把我們給識別出來才行。最早爬蟲在發(fā)出HTTP請求的時候,不注意偽裝自己,不會修改User Agent ,相當于告訴對方說: 我是爬蟲。
于是這些網(wǎng)站輕輕松松的就把我們識別出來,返回一個錯誤碼,或者干脆禁止我們訪問。
什么? 你還不知道什么是User Agent ?
User Agent其實就是HTTP Header 中的一個字符串,讓服務器端能識別客戶端的操作系統(tǒng)及版本,瀏覽器及版本,瀏覽器引擎,語言等等信息。 這樣可以針對性地做一些處理,例如發(fā)送桌面版或者手機版的網(wǎng)頁。
比如: User-Agent:Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)
后來我們也學精了,把這個User Agent 設置得和人類的瀏覽器一模一樣,對方就不好識別了。
有時候我們還可以偽裝成Google的爬蟲,百度的爬蟲, 各個網(wǎng)站自然希望百度和Google去對自己的網(wǎng)頁做索引的,所以對這樣的User Agent不會下狠手拒絕。
但是他們也有別的辦法,比如分析我們的行為,利用我們速度快的特點, 比如說,一秒之內有多少次請求,就認為是爬蟲。
我們也得斗智斗勇,訪問一會兒就休眠幾秒鐘,然后接著再訪問,讓他們的策略失效。
但是我們也不能老是休息呀,如果休息得太多,那我們就會人類的速度差不多了,爬蟲還有什么意義?
陷阱,驗證碼,投毒
有些網(wǎng)站會采取一些非常“惡劣”的手段,我最難以防范的就是陷阱。
具體來說,就是在網(wǎng)站發(fā)回的HTML頁面中,包含一些人類肉眼看不到的鏈接,比如弄個一個像素大小的圖片,上面有個鏈接。
人類看不到,是絕對不會點擊的,但是我們爬蟲是程序啊,能分析所有的鏈接并訪問之。 但是以我們的智商,并不知道這是一個陷阱啊!
這些陷阱就像漂浮在網(wǎng)頁中的幽靈, 只要我們一訪問這些鏈接,服務器立刻就會知道,哼哼,又來一個爬蟲,立刻啟動大殺招:封IP!
他們還有一招就是驗證碼, 如果一段時間內訪問的次數(shù)超過了某個閾值,立刻顯示一個圖形驗證碼,輸入驗證碼以后才能繼續(xù),這實在是太討厭了, 因為驗證碼是個圖片, 人類肉眼輕松識別,可是我想識別還得靠別的軟件或者系統(tǒng),比如OCR。
但是驗證現(xiàn)在搞得越來越復雜,什么滑塊驗證,什么數(shù)學題...... 單純的OCR都不夠了。
不過我也不怕,我可以做分布式,反正機器多,讓每個機器上的爬蟲運行得稍微慢一點,不要觸發(fā)服務器端的各種討厭的封鎖策略。
我還可以用代理,讓IP不斷變換,封了一個IP, 就用另外一個,子子孫孫無窮匱也。
我最煩的就是“投毒”,這一招最損, 網(wǎng)站識別出來我是爬蟲以后,并不會把我的IP關到小黑屋,而是很陰險地發(fā)送一些假數(shù)據(jù),和真實數(shù)據(jù)混在一起,讓我喜滋滋地取走,不知道過了多少天,主人用數(shù)據(jù)做分析時才發(fā)現(xiàn): 嗯,這數(shù)據(jù)有點不對頭啊! 到底是怎么回事!!! 于是我被拖出去打了50大板,真是冤枉啊。
新裝備
最近的日子有點不大對頭兒,訪問一個URL后,返回的HTML特別少,JS特別多,我從HTML中幾乎找不到什么有用的東西。
主人看到我干活效率驟然降低,趕緊親自上手研究了一番,他用Chrome打開網(wǎng)站,按F12, 查看源代碼和網(wǎng)絡請求, 嘆了一口氣說: “原來的辦法都不管用了,這些網(wǎng)站都在用JavaScript在瀏覽器端渲染了!”
不過他接著又興奮地說:“這也許是一件好事情,這些JavaScript通過AJAX的方式訪問后端網(wǎng)站的API,返回的數(shù)據(jù)都是JSON,我分析下,只要弄清楚這些API的輸入和輸出, 直接調用API就可以拿到數(shù)據(jù)了。”
其實都是分析,只不過原來分析HTML結構,從中取出內容,現(xiàn)在是分析后端服務器提供的API,直接獲取到了數(shù)據(jù),似乎更加方便。
但時候直接調用這些API也是有點小麻煩,比如很多時候,都需要進行認證,比如發(fā)個token什么的給服務器,要不然人家就不讓調用。
后來主人說,算了,實在是麻煩,我給我的爬蟲升級下裝備吧。
新裝備其實就是一個內嵌的瀏覽器,這個瀏覽器不需要界面顯示, 可以在程序中靜悄悄地執(zhí)行,主人把他叫做無界面瀏覽器,或者無頭瀏覽器。
(碼農(nóng)翻身注: 例如selenium,phantomjs等)
有了全功能的內嵌瀏覽器,相當于一個真正的人類在請求網(wǎng)頁了,把JavaScript下載下來,不是要在瀏覽器中做渲染嗎?等的就是你! 管你什么AJAX, token ,加密, 這里統(tǒng)統(tǒng)可以執(zhí)行。
這個無頭瀏覽器渲染完以后,我就可以拿到HTML做后續(xù)的分析了。
一切盡在掌握,這種感覺實在美妙。
不過缺點也是有的: 慢! 沒辦法,有得必有失嘛, 我們還可以采用分布式運行的利器,多跑一些爬蟲的實例,人多力量大。
總結
我們爬蟲界的終極目標就是和人類的行為保持一致,這樣就網(wǎng)站就無法識別了,只不過路漫漫其修遠兮,雙方的爭斗估計會一直持續(xù)下去。
在斗爭中,建議大家遵循一個原則:“斗而不破”, 不能砸網(wǎng)站的飯碗,要不然人家一怒之下把功能下線了,那大家徹底玩完。