前面我們講了《大規模非同步新聞爬蟲的實現思路》,在文章最後提到了把它升級為分散式的思路。今天,我們就來詳細實現一下,把它真正升級為分散式的大規模非同步爬蟲。
一、架構
我們設計的這個分散式是典型的CS架構,也就是分為伺服器端和客戶端。伺服器端我們稱為“爬蟲Server”,客戶端稱為“爬蟲Client”。
爬蟲Server,負責管理所有URL(即,爬蟲客戶端的下載任務)的狀態,透過我們前面介紹的UrlPool(網址池)進行管理。還不知道UrlPool的同學可以搜尋我們前面的文章,或者到《猿人學網站》上去看“Python爬蟲教程”找到UrlPool的講解。Server提供介面給Clients,以便它們獲取URL和提交URL。
爬蟲Client,負責URL的下載、網頁的解析以及儲存等各種。Client透過介面向Server請求需要被下載的URL,下載完成後向Server報告URL是否下載成功,同時把從網頁中提取到的URLs提交給Server,Server把它們放入URLPool。
Server和Client的分工明確,由它們組成的分散式爬蟲的架構就是這樣子的:
我們把這個分散式爬蟲叫做“bee”(小蜜蜂),寓意一群蜜蜂去採蜜。分別建立Server和Client的檔案:
bee_server.py
bee_client.py
二、爬蟲Server端實現
爬蟲Server端需要建立一個服務,它可以是TCP的,也可以是HTTP的。這裡,我們選擇Python的非同步web框架:Sanic 來寫這個服務。這個服務很簡單,程式碼如下:
上面是web服務的實現程式碼,透過
@app.listener(‘after_server_stop’)
在Server退出前,快取URLPool裡面的url。
整個web服務就實現了一個介面:/task, 透過GET方法讓client獲取URLs,透過POST讓client提交URLs。
後面再加上執行程式:
三、爬蟲Client的實現
我們把Client寫成一個類,這個類一部分介面是與Server互動用的,也就是從Server那裡獲取要下載的URL,以及向Server提交新得到的URLs。另外一部分介面是與網際網路互動的,即下載URLs。
透過非同步IO,我們可以把Client的併發提高上去,達到更高的抓取速度。
先來看看這個類的初始化:
其中,self._workers 記錄當前正在下載的協程(即,併發數);
sellf.workers_max 是限制最大併發數,根據自己的CPU效能和網路頻寬調整其大小,從而達到最大效率利用硬體資源。
download()方法是對aiohttp的封裝,方便非同步下載。
下面是與Server服務進行互動的兩個方法:
下面是下載任務相關的方法。其中save_html()根據自己需要可以把下載的網頁儲存到資料庫;filter_good()清洗提取到的URLs,把不需要下載的URLs扔掉。process()是個協程定義,它的工作就是下載、提取、儲存、提交,這個協程會在抓取迴圈中被不斷的建立,達到併發的目的。
最後,我們定義兩個迴圈,一個用於定時向Server請求要下載的URLs,另一個用於排程下載任務處理協程。透過self._workers這個計數器限制協程數量。start()方法就是整個類的執行入口。
最後的最後,我們需要執行Client:
四、執行和部署
執行過程很簡單,先執行Server程式:bee_server.py
再執行Client程式: bee_client.py
部署的話,可以單機也可以多機。
如果你的伺服器很強,多核的,單機可能就滿足你的下載量的需求了。首先執行一個Server,剩下client的執行數量根據核數來定。單核大約佔50%的CPU,自己多跑跑看。
如果你的下載量很大,比如實時抓取幾千家新聞網站,那麼可以多臺、多核進行部署。這時候,記得改一下Server監聽的host為0.0.0.0,以便其它機器能訪問它。
這就是一個分散式的爬蟲,道理很簡單,實現也不復雜。由於UrlPool的支援,你的Server可以隨時停掉重啟,然後繼續無重複下載。在這套程式碼上面,修改部分介面,就可以實現你自己的抓取目的。
老規矩,猿人學Python公眾號後臺回覆“bee”獲取相關程式碼。
———————————–
廣而告之,最近我在教爬蟲
一對一教學Python爬蟲;
學會如何設計抓取海量資料的爬蟲;
學會如何分析/反反爬策略;
學完自己能真實動手開發那種;
在猿人學Python公眾號選單欄-聯絡我,找到我的微信。
爬蟲文章擴充閱讀:
我的公眾號:猿人學 Python 上會分享更多心得體會,敬請關注。
***版權申明:若沒有特殊說明,文章皆是猿人學 yuanrenxue.com 原創,沒有猿人學授權,請勿以任何形式轉載。***