如何利用python asyncio編寫非同步爬蟲?

打算利用asyncio寫一個非同步的爬蟲,有一定概念,但還是難以開始寫。
大概的想法是把爬蟲的網路io和資料庫io做成非同步的,其它的parse、extract_link什麼的用生成器實現,然後交給event_loop調度。

但是從未寫過這種代碼,不知道該從何寫起。

1.寫這種程序如何組織代碼?
2.能否推薦一些使用asyncio寫的項目,讓我參考學習一下?
3.如果要使用selenium + phantomjs來讀取頁面的話又該如何去寫非同步?
4.接3,有一個小疑問,selenium + phantomjs能否同時創建多個webdriver實例去處理頁面(我拿4個線程分別獲取4個url,簡單測了一下,感覺可以)?

謝謝


你可以用AioHttp,它把HTTP封裝好了。
當然你也可以自己依靠asyncio的create connection寫一個框架。
我這裡建議使用Python 3.5。你可以用await和async def 區分協程和生成器。

言歸正傳,
首先,你應該謹慎使用協程,只有在涉及到IO的時候,使用才是合理的。
我不理解為什麼parse, extract_link這種顯然非阻塞的程序,你要用生成器。生成器並不是多進程,不是你寫成協程的形式,速度就蹭蹭蹭上去的。而且大量無意義的協程跳來跳去,並不比回調的CallBack Hell好多少。你在Debug的時候,還是不能完全知道事情發生的先後順序。

所以程序應該分為2部分,一部分是AioHttp,對網站進行採集,這部分一個event_loop卡住主線程。你可以自己決定開多少協程。Tip:你可以不用Queue,直接用list就好了。協程一般不用加鎖。
當資源收集完畢之後,主線程繼續,進行洗數據和分析數據,非常簡單直觀的一個架構。

然後,selenium + phantomjs。明白了協程的邏輯,你就應該明白,把一個阻塞庫selenium 放進協程是毫無意義的。想要提速,只能使用多線程。Tip:selenium 永遠只會開新的實例,所以如果有時候崩潰了 phantomjs並不會關閉,多了就內存泄漏了。

但也不是完全沒有辦法,你可以把不需要js的用aiohttp抓,需要js的單獨用selenium放進一個線程池。


可以在github搜索一下500lines這個項目合集,裡面有一個叫crawler的項目,是一個利用asyncio庫實現的非同步網路爬蟲,由Guido van Rossum編寫。


https://github.com/xxNB/crawl

有幫助的話給個star~


asyncio應該也是利用多路服用網路IO開發的一套協程處理機切換框架(非同步通信),用來加快網路IO相關的編程。所以,可以用這套框架做一個發送http和接收數據非同步通信的framework,用來加快發送和接收的處理速度。利用multiprocessing起一個這樣的服務,再起一個用來和這個framework的交互的進程(利用共享隊列交互待爬取的url 和 接收到的內容)。這樣就完美了。


前段時間租房,正好用 asyncio 寫了個豆瓣租房玩具小爬蟲

https://gist.github.com/cosven/2aab9f406e12f36ae24f1e9d76a297d0

hello world 項目,你值得擁有 23333


為什麼不試一試
gevent呢? gevent上手快很多


推薦閱讀:

如何用八爪魚採集器提取新浪微博的數據呢?
python抓取網易財經的個股的財務數據,比如利潤表,並分項保存到mysql,需要哪些步驟?
啟信寶的查詢功能是如何實現的?
怎樣利用數據爬取和分析工具寫出《黃燜雞米飯是怎麼火起來的》這樣的文章?

TAG:Python | 爬蟲計算機網路 | 非同步IO |