python爬取github數據

爬蟲流程

在上周寫完用scrapy爬去知乎用戶信息的爬蟲之後,github上star個數一下就在公司小組內部排的上名次了,我還信誓旦旦的跟上級吹牛皮說如果再寫一個,都不好意思和你再提star了,怕你們傷心。上級不屑的說,那就寫一個爬蟲爬一爬github,找一找python大牛,公司也正好在找人。臨危受命,格外激動,當天就去研究github網站,琢磨怎麼解析頁面以及爬蟲的運行策略。意外的發現github提供了非常nice的API以及文檔文檔,讓我對github的愛已經深入骨髓。

說了這麼多廢話,講講真題吧。我需要下載github用戶還有他們的reposities數據,展開方式也很簡單,根據一個用戶的following以及follower關係,遍歷整個用戶網就可以下載所有的數據了,聽說github註冊用戶才幾百萬,一下就把所有的數據爬下來想想還有點小激動呢,下面是流程圖:

這是我根據這個流程實現的代碼,網址:LiuRoy/github_spider

遞歸實現

運行命令

看到這麼簡單的流程,內心的第一想法就是先簡單的寫一個遞歸實現唄,要是性能差再慢慢優化,所以第一版代碼很快就完成了(在目錄recursion下)。數據存儲使用mongo,重複請求判斷使用的redis,寫mongo數據採用celery的非同步調用,需要rabbitmq服務正常啟動,在settings.py正確配置後,使用下面的步驟啟動:

  1. 進入github_spider目錄
  2. 執行命令celery -A github_spider.worker worker loglevel=info啟動非同步任務
  3. 執行命令python github_spider/recursion/main.py啟動爬蟲

運行結果

因為每個請求延時很高,爬蟲運行效率很慢,訪問了幾千個請求之後拿到了部分數據,這是按照查看數降序排列的python項目:

這是按粉絲數降序排列的用戶列表

運行缺陷

作為一個有追求的程序員,當然不能因為一點小成就滿足,總結一下遞歸實現的幾個缺陷:

  1. 因為是深度優先,當整個用戶圖很大的時候,單機遞歸可能造成內存溢出從而使程序崩潰,只能在單機短時間運行。
  2. 單個請求延時過長,數據下載速度太慢。
  3. 針對一段時間內訪問失敗的鏈接沒有重試機制,存在數據丟失的可能。

非同步優化

針對這種I/O耗時的問題,解決方法也就那幾種,要麼多並發,要麼走非同步訪問,要麼雙管齊下。針對上面的問題2,我最開始的解決方式是非同步請求API。因為最開始寫代碼的時候考慮到了這點,代碼對調用方法已經做過優化,很快就改好了,實現方式使用了grequests。這個庫和requests是同一個作者,代碼也非常的簡單,就是講request請求用gevent做了一個簡單的封裝,可以非阻塞的請求數據。

但是當我運行之後,發現程序很快運行結束,一查發現公網IP被github封掉了,當時心中千萬隻草泥馬奔騰而過,沒辦法只能祭出爬蟲的終極殺器--代理。又專門寫了一個輔助腳本從網上爬取免費的HTTPS代理存放在redis中,路徑proxy/extract.py,每次請求的時候都帶上代理,運行錯誤重試自動更換代理並把錯誤代理清楚。本來網上免費的HTTPS代理就很少,而且很多還不能用,由於大量的報錯重試,訪問速度不僅沒有原來快,而且比原來慢一大截,此路不通只能走多並發實現了。

隊列實現

實現原理

採取廣度優先的遍歷的方式,可以把要訪問的網址存放在隊列中,再套用生產者消費者的模式就可以很容易的實現多並發,從而解決上面的問題2。如果某段時間內一直失敗,只需要將數據再仍會隊列就可以徹底解決問題3。不僅如此,這種方式還可以支持中斷後繼續運行,程序流程圖如下:

運行程序

為了實現多級部署(雖然我就只有一台機器),消息隊列使用了rabbitmq,需要創建名為github,類型是direct的exchange,然後創建四個名稱分別為user, repo, follower, following的隊列,詳細的綁定關係見下圖:

詳細的啟動步驟如下:

  1. 進入github_spider目錄
  2. 執行命令celery -A github_spider.worker worker loglevel=info啟動非同步任務
  3. 執行命令python github_spider/proxy/extract.py更新代理
  4. 執行命令python github_spider/queue/main.py啟動腳本

隊列狀態圖:

作者:腩啵兔子

出處:腩啵兔子的博客專欄

最近很多人私信問我問題,平常知乎評論看到不多,如果沒有及時回復,大家也可以加小編微信:tszhihu,進知乎大數據分析挖掘交流群,可以跟各位老師互相交流。謝謝。


推薦閱讀:

基於TCP的python聊天程序
學會最簡單的資料庫|看完這7招就夠了
Python 高級編程:理解生成器
Python Generator漫談
在 Pycom 使用 Python + Micropython + MQTT 進行物聯網編程

TAG:Python | GitHub | 爬虫 |