一個不簡單的非同步爬蟲小程序
說到Python,爬蟲可能是大家第一個想到的。
然而,Python在爬蟲方面已經產生了巨大的變化。雖然本次的小程序並不簡單,不過你們可以嘗試著了解一下,在Python3中如何書寫一個爬蟲。
相關庫
本次,我們使用的庫並不是`requests`庫,而是僅僅支持`Python3.4.2+`的`aiohttp`。
首先我們需要搭建相關的環境:
安裝`aiohttp`
pip install aiohttp
安裝`cchardet`
pip3 install cchardet
安裝`aiodns`
pip3 install aiodns
以上庫基本上都沒有依賴問題,可以直接安裝。
## 目標
例如:`URL — http://flupy.org/data/flags/cn/cn.gif`的內容是一面中國國旗(希望大家做一個愛國的好公民)

當然,國旗不只這一面,我們我們只要吧`url`中的`cn/cn.gif`換成別的國家,就可以拿到別的國家的旗子。
例如:`URL — http://flupy.org/data/flags/us/us.gif`的內容是一面美國國旗(us是美國的國家代碼)

因此,我們今天的目標就是:
`CN IN US ID BR PK NG BD RU JP MX PH VN ET EG DE IR TR CD FR`
這20個旗子
構造URL代碼
為了構造這些目標,我們必須要先獲得URL,因此我們通過`base_url`和`contry_codes`的形式分別存儲URL共同的部分與不同的部分。
程序設計
主流程:
主流程一半是出現再`__name__`測試中的入口函數,使用它的目的一半是提供一個統一的介面,並且提供一個清晰的邏輯,以方便我們添加一些額外的信息。
該主流程,只有兩個功能
1. 用來調用本程序真正的代碼
2. 用來對整個代碼的執行計時
實際流程:
在實際的流程中,我們需要開啟一個事件循環,來處理我們的任務。
因此我們需要得到一個事件循環`loop`。來執行我們非阻塞的`coroutine`。當然,時間循環一單用完,需要關閉。
在這個流程中,`wait`可以通過許多的`coroutine`來構造一個非阻塞的`coroutine`。而且最後這個`coroutine`是在所有`coroutine`完成時才完成。
其實這個流程也只完成了兩件事:
* 構造了循環
* 構造需要被時間循環執行的`coroutine`,並提交給循環
處理單個爬取的coroutine
記住,`download_many`的依然是一個普通的函數,但是它的作用是操作時間循環去調度`coroutine`,因此我們需要開始寫我們的`coroutine`。
由上一部分可知,對應沒一個旗子的`download_one`就是一個`coroutine`
此處分塊處理的原因是因為,不確定圖片的大小,可以保證不要一次性佔用太多的內存空間。
從上面看出,所有的`coroutine`都是非同步的,如果讀者自己嘗試一下。就會發現,與普通的排隊式爬蟲相比,速度提高了近16倍,甚至更多。
與使用多線程爬蟲的效果相當,但是佔用更少的資源,可以騰出更多的內存空間。
待改進
其實在此處,埋了一個伏筆,本程序還有待改進,它現在唯一不完美的地方是,對`pool`的重複利用不好,最好把session放入download_many中。
關注+轉發
謝謝親們


※記,用Python分析農藥,打出了一次超6的團戰!
※Python必學基礎概念
※python最牛web框架居然是「它」
※十張圖讀懂 PHP、Python、Ruby 三大語言的差異
※為啥我的Python這麼慢(一)
TAG:python |