為什麼每一個爬蟲工程師都應該學習 Kafka

青南發表於2019-12-14

這篇文章不會涉及到Kafka 的具體操作,而是告訴你 Kafka 是什麼,以及它能在爬蟲開發中扮演什麼重要角色。

一個簡單的需求

假設我們需要寫一個微博爬蟲,老闆給的需求如下:

為什麼每一個爬蟲工程師都應該學習 Kafka

開發爬蟲對你來說非常簡單,於是三下五除二你就把爬蟲開發好了:

為什麼每一個爬蟲工程師都應該學習 Kafka

接下來開始做報警功能,邏輯也非常簡單:

為什麼每一個爬蟲工程師都應該學習 Kafka

再來看看統計關鍵詞的功能,這個功能背後有一個網頁,會實時顯示抓取資料量的變化情況,可以顯示每分鐘、每小時的某個關鍵詞的抓取量。

這個功能對你來說也挺簡單,於是你實現瞭如下邏輯:

為什麼每一個爬蟲工程師都應該學習 Kafka

最後一個需求,對微博資料進行情感分析。情感分析的模組有別的部門同事開發,你要做的就是每個小時拉取一批資料,傳送到介面,獲取返回,然後存入後端需要的資料庫:

為什麼每一個爬蟲工程師都應該學習 Kafka

任務完成,於是你高興地回家睡覺了。

困難接踵而至

爬蟲變慢了

隨著老闆逐漸增加新的關鍵詞,你發現每一次完整抓取的時間越來越長,一開始是2分鐘抓取一輪,後來變成10分鐘一輪,然後變成30分鐘一輪,接下來變成1小時才能抓取一輪。隨著延遲越來越高,你的報警越來越不準確,微博都發出來一小時了,你的報警還沒有發出來,因為那一條微博還沒有來得及入庫。

你的爬蟲技術非常好,能繞過所有反爬蟲機制,你有無限個代理 IP,於是你輕輕鬆鬆就把爬蟲提高到了每秒一百萬併發。現在只需要1分鐘你就能完成全部資料的抓取。這下沒問題了吧。

可是報警還是沒有發出來。這是怎麼回事?

資料庫撐不住了

經過排查,你發現了問題。資料抓取量上來了,但是 MongoDB 卻無法同時接收那麼多的資料寫入。資料寫入速度遠遠小於爬取資料,大量的資料堆積在記憶體中。於是你的伺服器爆炸了。

你緊急搭建了100個資料庫並編號0-99,對於抓取到的微博,先把每一條微博的 ID對100求餘數,然後把資料存入餘數對應的 MongoDB 中。每一臺 MongoDB 的壓力下降到了原來的1%。資料終於可以即時存進資料庫裡面了。

可是報警還是沒有發出來,不僅如此,現在實時抓取量統計功能也不能用了,還有什麼問題?

查詢來不及了

現在報警程式要遍歷100個資料庫最近5分鐘裡面的每一條資料,確認是否有需要報警的內容。但是這個遍歷過程就遠遠超過5分鐘。

時間錯開了

由於微博的綜合搜尋功能不是按照時間排序的,那麼就會出現這樣一種情況,早上10:01發的微博,你在12:02的時候才抓到。

不論你是在報警的時候篩選資料,還是篩選資料推送給 NLP 分析介面,如果你是以微博的釋出時間來搜尋,那麼這一條都會被你直接漏掉——當你在10:05的時候檢索10:00-10:05這5分鐘發表的微博,由於這一條微博沒有抓到,你自然搜尋不到。

當你12:05開始檢索12:00-12:05的資料時,你搜尋的是釋出時間為12:00-12:05的資料,於是10:01這條資料雖然是在12:02抓到的,但你也無法篩選出來。

那麼是不是可以用抓取時間來搜尋呢?例如10:05開始檢索在10:00-10:05抓取到的資料,無論它的釋出時間是多少,都檢索出來。

這樣做確實可以保證不漏掉資料,但這樣做的代價是你必需儲存、檢索非常非常多的資料。例如每次抓取,只要釋出時間是最近10小時的,都要儲存下來。於是報警程式在檢索資料時,就需要檢索這5分鐘入庫的,實際上釋出時間在10小時內的全部資料。

什麼,你說每次儲存之前檢查一下這條微博是否已經存在,如果存在就不儲存?別忘了批量寫入時間都不夠了,你還準備分一些時間去查詢?

髒資料來了

老闆突然來跟你說,關鍵詞“籃球”裡面有大量的關於 蔡徐坤的內容,所以要你把所有包含蔡徐坤的資料全部刪掉。

那麼,這個過濾邏輯放在哪裡?放在爬蟲的 pipelines.py 裡面嗎?那你要重新部署所有爬蟲。今天是過濾蔡徐坤,明天是過濾範層層,後天是過濾王一博,每天增加關鍵詞,你每天都得重新部署爬蟲?

那你把關鍵詞放在 Redis 或者 MongoDB 裡面,每次插入資料前,讀取所有關鍵詞,看微博裡面不包含再存。

還是那個問題,插入時間本來就不夠了,你還要查資料庫?

好,關鍵詞過濾不放在爬蟲裡面了。你寫了一個指令碼,每分鐘檢查一次MongoDB新增的資料,如果發現包含 不需要的關鍵詞,就把他刪除。

現在問題來了,刪除資料的程式每分鐘檢查一次,報警程式每5分鐘檢查一次。中間必定存在某些資料,還沒有來得及刪除,報警程式就報警了,老闆收到報警來看資料,而你的刪除程式又在這時把這個髒資料刪了。

這下好了,天天報假警,狼來了的故事重演了。

5個問題1個救星

如果你在爬蟲開發的過程中遇到過上面的諸多問題,那麼,你就應該試一試使用 Kafka。一次性解決上面的所有問題。

把 Kafka 加入到你的爬蟲流程中,那麼你的爬蟲架構變成了下面這樣:

為什麼每一個爬蟲工程師都應該學習 Kafka

這看起來似乎和資料直接寫進 MongoDB 裡面,然後各個程式讀取 MongoDB 沒什麼區別啊?那 Kafka 能解決什麼問題?

我們來看看,在這個爬蟲架構裡面,我們將會用到的 Kafka 的特性:

為什麼每一個爬蟲工程師都應該學習 Kafka

與其說 Kafka 在這個爬蟲架構中像 MongoDB,不如說更像 Redis 的列表。

現在來簡化一下我們的模型,如果現在爬蟲只有一個需求,就是搜尋,然後報警。那麼我們可以這樣設計:

為什麼每一個爬蟲工程師都應該學習 Kafka

爬蟲爬下來的資料,直接塞進 Redis 的列表右側。報警程式從 Redis 列表左側一條一條讀取。讀取一條檢視一條,如果包含報警關鍵詞,就報警。然後讀取下一條。

這樣做有什麼好處?

為什麼每一個爬蟲工程師都應該學習 Kafka

因為報警程式直接從 Redis 裡面一條一條讀取,不存在按時間搜尋資料的過程,所以不會有資料延遲的問題。由於 Redis 是單執行緒資料庫,所以可以同時啟動很多個報警程式。由於 lpop 讀取一條就刪除一條,如果報警程式因為某種原因崩潰了,再把它啟動起來即可,它會接著工作,不會重複報警。

但使用 Redis 列表的優勢也是劣勢:列表中的資訊只能消費1次,被彈出了就沒有了。

所以如果既需要報警,還需要把資料存入 MongoDB 備份,那麼只有一個辦法,就是報警程式檢查完資料以後,把資料存入 MongoDB。

可我只是一個哨兵,為什麼要讓我做後勤兵的工作?

一個報警程式,讓它做報警的事情就好了,它不應該做儲存資料的事情。

而使用 Kafka,它有 Redis 列表的這些好處,但又沒有 Redis 列表的弊端!

我們完全可以分別實現4個程式,不同程式之間消費資料的快慢互不影響。但同一個程式,無論是關閉再開啟,還是同時執行多次,都不會重複消費。

程式1:報警

從 Kafka 中一條一條讀取資料,做報警相關的工作。程式1可以同時啟動多個。關了再重新開啟也不會重複消費。

程式2:儲存原始資料

這個程式從 Kafka 中一條一條讀取資料,每湊夠1000條就批量寫入到 MongoDB 中。這個程式不要求實時儲存資料,有延遲也沒關係。 存入MongoDB中也只是原始資料存檔。一般情況下不會再從 MongoDB 裡面讀取出來。

程式3:統計

從 Kafka 中讀取資料,記錄關鍵詞、釋出時間。按小時和分鐘分別對每個關鍵詞的微博計數。最後把計數結果儲存下來。

程式4:情感分析

從 Kafka 中讀取每一條資料,湊夠一批傳送給 NLP 分析介面。拿到結果存入後端資料庫中。

如果要清洗資料怎麼辦

4個需求都解決了,那麼如果還是需要你首先移除髒資料,再分析怎麼辦呢?實際上非常簡單,你加一個 Kafka(Topic) 就好了!

為什麼每一個爬蟲工程師都應該學習 Kafka

大批量通用爬蟲

除了上面的微博例子以外,我們再來看看在開發通用爬蟲的時候,如何應用 Kafka。

在任何時候,無論是 XPath 提取資料還是解析網站返回的 JSON,都不是爬蟲開發的主要工作。爬蟲開發的主要工作一直是爬蟲的排程和反爬蟲的開發。

我們現在寫 Scrapy 的時候,處理反爬蟲的邏輯和提取資料的邏輯都是寫在一個爬蟲專案中的,那麼在開發的時候實際上很難實現多人協作。

現在我們把網站內容的爬蟲和資料提取分開,實現下面這樣一個爬蟲架構:

為什麼每一個爬蟲工程師都應該學習 Kafka

爬蟲開發技術好的同學,負責實現繞過反爬蟲,獲取網站的內容,無論是 HTML 原始碼還是介面返回的JSON。拿到以後,直接塞進 Kafka。

爬蟲技術相對一般的同學、實習生,需要做的只是從 Kafka 裡面獲取資料,不需要關心這個資料是來自於 Scrapy 還是 Selenium。他們要做的只是把這些HTML 或者JSON 按照產品要求解析成格式化的資料,然後塞進 Kafka,供後續資料分析的同學繼續讀取並使用。

如此一來,一個資料小組的工作就分開了,每個人做各自負責的事情,約定好格式,同步開發,互不影響。

為什麼是 Kafka 而不是其他

上面描述的功能,實際上有不少 MQ 都能實現。但為什麼是 Kafka 而不是其他呢?因為Kafka 叢集的效能非常高,在垃圾電腦上搭建的叢集能抗住每秒10萬併發的資料寫入量。而如果選擇效能好一些的伺服器,每秒100萬的資料寫入也能輕鬆應對。

總結

這篇文章通過兩個例子介紹了 Kafka 在爬蟲開發中的作用。作為一個爬蟲工程師,作為我的讀者。請一定要掌握 Kafka。

下一篇文章,我們來講講如何使用 Kafka。比你在網上看到的教程會更簡單,更容易懂。

為什麼每一個爬蟲工程師都應該學習 Kafka

關注本公眾號,回覆“爬蟲與Kafka”獲取本文對應的思維導圖原圖。

相關文章