回覆列表
  • 1 # soundwave

    一、爬蟲工程師是幹嘛的?

    1.主要工作內容?

    網際網路是由一個一個的超連結組成的,從一個網頁的連結可以跳到另一個網頁,在新的網頁裡,又有很多連結。理論上講,從任何一個網頁開始,不斷點開連結、連結的網頁的連結,就可以走遍整個網際網路!這個過程是不是像蜘蛛沿著網一樣爬?這也是“爬蟲”名字的由來。

    作為爬蟲工程師,就是要寫出一些能夠沿著網爬的”蜘蛛“程式,儲存下來獲得的資訊。一般來說,需要爬出來的資訊都是結構化的,如果不是結構化的,那麼也就沒什麼意義了(百分之八十的資料是非結構化的)。爬蟲的規模可達可小,小到可以爬取豆瓣的top 250電影,定時爬取一個星期的天氣預報等。大到可以爬取整個網際網路的網頁(例如google)。下面這些,我認為都可以叫做爬蟲:

    1.爬知乎的作者和回答

    2.爬百度網盤的資源,存到資料庫中(當然,只是儲存資源的連結和標題),然後製作一個網盤的搜尋引擎

    3.同上,種子網站的搜尋引擎也是這樣的

    到這裡,我們知道爬蟲的任務是獲取資料。現在比較流行大資料,從網際網路方面講,資料可以分成兩種,一種是使用者產生的(UGC),第二種就是透過一些手段獲得的,通常就是爬蟲。爬蟲又不僅僅侷限於從網頁中獲得資料,也可以從app抓包等。簡而言之,就是聚合資料並讓他們結構化。那麼,哪些工作需要爬蟲呢?

    2.爬蟲能做什麼?

    典型的資料聚合類的網站都需要爬蟲。比如Google搜尋引擎。Google能在幾毫秒之內提供給你包含某些關鍵字的頁面,肯定不是實時給你去找網頁的,而是提前抓好,儲存在他們自己的資料庫裡(那他們的資料庫得多大呀)。所以種子搜尋引擎,網盤搜尋引擎,Resillio key引擎等都是用爬蟲實現抓好資料放在資料庫裡的。

    除此之外,個人還可以用爬蟲做一些好玩的事情。比如我們想看大量的圖片,可以寫一個爬蟲批次下載下來,不必一個一個點選儲存,還要忍受網站的廣告了;比如我們想備份自己的資料,例如儲存下來我們在豆瓣釋出過的所有的廣播,可以使用爬蟲將自己釋出的內容全部抓下來,這樣即使一些網站沒有提供備份服務,我們也可以自己豐衣足食。

    二、爬蟲工程師需要掌握哪些技能?

    我見過這樣的說法:“爬蟲是低階、重複性很多的工作,沒有發展前途”。這是誤解。首先,對於程式設計師來說基本上不存在重複性的工作,任何重複勞動都可以透過程式自動解決。例如博主之前要抓十幾個相似度很高但是html結構不太一樣的網站,我就寫了一個簡單的程式碼生成器,從爬蟲程式碼到單元測試程式碼都可以自動生成,只要對應html結構稍微修改一下就行了。所以我認為,重複性的勞動在程式設計方面來說基本上是不存在的,如果你認為自己做的工作是重複性的,說明你比較勤快,不願意去偷懶。而我還認為,勤快的程式設計師不是好程式設計師。下面我根據自己這段時間的工作經歷,講一講爬蟲需要哪些相關的技能。

    1.基本的編碼基礎(至少一門程式語言)

    這個對於任何程式設計工作來說都是必須的。基礎的資料結構你得會吧。資料名字和值得對應(字典),對一些url進行處理(列表)等等。事實上,掌握的越牢固越好,爬蟲並不是一個簡單的工作,也並不比其他工作對程式語言的要求更高。熟悉你用的程式語言,熟悉相關的框架和庫永遠是百益無害。

    我主要用Python,用Java寫爬蟲的也有,理論上講任何語言都可以寫爬蟲的,不過最好選擇一門相關的庫多,開發迅速的語言。用C語言寫肯定是自找苦吃了。

    2.任務佇列

    當爬蟲任務很大的時候,寫一個程式跑下來是不合適的:

    1.如果中間遇到錯誤停掉,重頭再來?這不科學

    2.我怎麼知道程式在哪裡失敗了?任務和任務之間不應該相互影響

    3.如果我有兩臺機器怎麼分工?

    所以我們需要一種任務佇列,它的作用是:講計劃抓取的網頁都放到任務佇列裡面去。然後worker從佇列中拿出來一個一個執行,如果一個失敗,記錄一下,然後執行下一個。這樣,worker就可以一個接一個地執行下去。也增加了擴充套件性,幾億個任務放在佇列裡也沒問題,有需要可以增加worker,就像多一雙虧筷子吃飯一樣。

    常用的任務佇列有kafka,beanstalkd,celery等。

    3.資料庫

    這個不用講了,資料儲存肯定要會資料庫的。不過有時候一些小資料也可以儲存成json或者csv等。我有時想抓一些圖片就直接按照資料夾儲存檔案。

    推薦使用NoSQL的資料庫,比如mongodb,因為爬蟲抓到的資料一般是都欄位-值得對應,有些欄位有的網站有有的網站沒有,mongo在這方面比較靈活,況且爬蟲爬到的資料關係非常非常弱,很少會用到表與表的關係。

    4.HTTP知識

    HTTP知識是必備技能。因為要爬的是網頁,所以必須要了解網頁啊。

    首先html文件的解析方法要懂,比如子節點父節點,屬性這些。我們看到的網頁是五彩斑斕的,只不過是被瀏覽器處理了而已,原始的網頁是由很多標籤組成的。處理最好使用html的解析器,如果自己用正則匹配的話坑會很多。我個人非常喜歡xpath,跨語言,表達比價好,但是也有缺點,正則、邏輯判斷有點彆扭。

    HTTP協議要理解。HTTP協議本身是無狀態的,那麼“登入”是怎麼實現的?這就要求去了解一下session和cookies了。GET方法和POST方法的區別(事實上除了字面意思不一樣沒有任何區別)。

    瀏覽器要熟練。爬蟲的過程其實是模擬人類去瀏覽器資料的過程。所以瀏覽器是怎麼訪問一個網站的,你要學會去觀察,怎麼觀察呢?Developer Tools!Chrome的Developer Tools提供了訪問網站的一切資訊。從traffic可以看到所有發出去的請求。copy as curl功能可以給你生成和瀏覽器請求完全一致的curl請求!我寫一個爬蟲的一般流程是這樣的,先用瀏覽器訪問,然後copy as curl看看有哪些header,cookies,然後用程式碼模擬出來這個請求,最後處理請求的結果儲存下來。

    5.運維

    這個話題要說的有很多,實際工作中運維和開發的時間差不多甚至更多一些。維護已經在工作的爬蟲是一個繁重的工作。隨著工作時間增加,一般我們都會學著讓寫出來的爬蟲更好維護一些。比如爬蟲的日誌系統,資料量的統計等。將爬蟲工程師和運維分開也不太合理,因為如果一個爬蟲不工作了,那原因可能是要抓的網頁更新了結構,也有可能出現在系統上,也有可能是當初開發爬蟲的時候沒發現反扒策略,上線之後出問題了,也可能是對方網站發現了你是爬蟲把你封殺了,所以一般來說開發爬蟲要兼顧運維。

    所以爬蟲的運維我可以提供下面幾個思路:

    首先,從資料增量監控。定向爬蟲(指的是隻針對一個網站的爬蟲)比較容易,一段時間之後對一些網站的資料增量會有一個大體的瞭解。經常看看這些資料的增加趨勢是否是正常就可以了(Grafana)。非定向爬蟲的資料增量不是很穩定,一般看機器的網路狀況,網站的更新情況等(這方面我的經驗不多)。

    然後看爬蟲執行的成功情況。在上面提到了用任務佇列控制爬蟲工作,這樣解耦可以帶來很多好處,其中一個就是可以就是可以對一次爬蟲執行進行日誌。可以在每次爬蟲任務執行的時候,將執行的時間、狀態、目標url、異常等放入一個日誌系統(比如kibana),然後透過一個視覺化的手段可以清晰地看到爬蟲的失敗率。

    爬蟲丟擲的Exception。幾乎所有的專案都會用到錯誤日誌收集(Sentry),這裡需要注意的一點是,忽略正常的異常(比如Connection錯誤,鎖衝突等),否則的話你會被這些錯誤淹沒。

    三、爬蟲與反爬

    這同樣是很深的一個話題,就像攻擊武器與防禦武器一樣,雙方總是在不斷升級。常見的反爬措施(我遇到過的)有下面幾種:

    1.訪問頻率

    很好理解,如果訪問太頻繁網站可能針對你的ip封鎖一段時間,這和防DDoS的原理一樣。對於爬蟲來說,碰到這樣的限制一下任務的頻率就可以了,可以儘量讓爬蟲想人類一樣訪問網頁(比如隨機sleep一段時間,如果每隔3s訪問一次網站很顯然不是正常人的行為)。

    2.登入限制

    也比較常見。不過公開資訊的網站一般不會有這個限制,這樣讓使用者也麻煩了。其實反爬措施都或多或少的影響真實使用者,反爬越嚴格,誤殺使用者的可能性也越高。對爬蟲來說,登入同樣可以透過模擬登入的方式解決,加個cookie就行了(話又說回來,網路的原理很重要)。

    3.透過Header封殺

    一般瀏覽器訪問網站會有header,比如Safari或者Chrome等等,還有作業系統資訊。如果使用程式訪問並不會有這樣的header。破解也很簡單,訪問的時候加上header就行。

    4.JavaScript指令碼動態獲取網站資料

    有一些網站(尤其是單頁面網站)的內容並不是透過伺服器直接返回的,而是伺服器只返回一個客戶端JavaScript程式,然後JavaScript獲取內容。更高階的是,JavaScript在本地計算一個token,然後拿這個token來進行AJAX獲取內容。而本地的JavaScript又是經過程式碼混淆和加密的,這樣我們做爬蟲的透過看原始碼幾乎不可能模擬出來這個請求(主要是token不可能破解),但是我們可以從另一個角度:headless的瀏覽器,也就是我們直接執行這個客戶端程式,這可以100%地模擬真實使用者!

    5.驗證碼

    這幾乎是終極武器了,驗證碼是專門用來區分人和計算機的手段。對於反爬方來說,這種方式對真實使用者和搜尋引擎(其實可以透過記錄搜尋引擎爬蟲的ip來區別對待,可以解決)的危害比較大,相信讀者都有輸入驗證碼的痛苦經歷。但這種方法也並不是無敵的!透過現在很火的機器學習可以輕鬆的識別大部分的驗證碼!Google的reCAPTCHA是一種非常高階的驗證碼,但是聽過透過模擬瀏覽器也是可以破解的。

    6.ip限制

    網站可能將識別的ip永久封殺,這種方式需要的人力比較大,而且誤傷使用者的代價也很高。但是破解辦法卻非常簡單。目前代理池幾乎是搞爬蟲的標配了,甚至還有很多高匿代理等好用的東西。所以這基本上只能殺殺小爬蟲。

    7.網站內容反爬

    有一些網站將網站內容用只有人類可以接收的形式來呈現(其實反爬就是區別對待人類和機器嘛)。比如將內容用圖片的形式顯示。但是近幾年來人類和機器的差別越來越小,圖片可以用OCR準確率非常高地去識別。

    反爬總結

    爬蟲和反爬是典型的攻防雙方的互相升級。但是我認為,這種升級不像軍事,軍事是無盡頭的,但是爬蟲和反爬是有盡頭的。

    爬蟲的盡頭就是瀏覽器,一旦使用瀏覽器,程式完全可以模擬真實使用者發出請求,缺點是就是消耗資源,因為需要新開一個程序,解析DOM,執行客戶端JavaScript程式碼。(chrome的node api在github開源僅僅兩天,就拿到8k個star)

    反爬的盡頭就是像Google這種超級厲害的驗證碼,畢竟驗證碼的根本目的就是識別人類和機器的。

    我正好有一個反爬做的非常好的例子。Google Arts Project專案是一個匯聚世界名畫的藝術長廊,我比較喜歡裡面的一些畫,所以想下載一些(當然這是不對的),然後發現這個網站反爬做的相當好(因為版權屬於收藏作品的博物館,所以Google Arts Project肯定不會提供下載),要下載幾乎是不可能的。我有點不服,開始用各種手段試圖下載原圖。嘗試了一番,發現這個網站block掉了滑鼠右鍵功能、審查元素髮現圖片並不是一個常規的圖片、追蹤網路包發現原圖竟然不是一次網路請求拿到的,而是分成了好幾次請求base64編碼的字元流每次請求圖片的一部分,然後在客戶端組裝起來圖片!當然在客戶端的程式碼也是經過加密和混淆的!這完全可以作為反爬的教科書了,既沒有誤傷使用者,又讓爬蟲無法下手。

    圖片每次只請求部分

    四、職業道德

    成規模的爬蟲一般都會使用叢集,一般的小網站伺服器規模可能不如爬蟲叢集的規模大。所以很多時候我們最好對要爬的網站限制一下頻率。否則這些爬蟲就相當於DoS攻擊叢集了!一般的網站都會有robots.txt可以參考。

    好了,總結來說,寫爬蟲需要經驗積累,需要靈活的思路。比如說我之前就遇到過網站,需要驗證碼驗證拿到一個token,可是透過看網路請求發現這個token長得很像一個時間戳,然後本地自己生成一個時間戳發現也是能用的!於是就這樣繞過了驗證碼。所以多多積累和嘗試,可以偷不少懶,嘿嘿。

    另外爬蟲也不是和我之前想的那樣是一個枯燥無味的工作,比如我就發現了不少很垃圾,很搞笑的網站,樂趣也蠻多的。學到的東西也不少。萬變不離其宗嘛。

  • 中秋節和大豐收的關聯?
  • 假期快要到了,大家想好去哪裡遊玩了嗎?