越寫越像官方文檔的翻譯,偏離了初衷。寫一些官方文檔里沒有的內容吧。
- 在不限制寬帶的環境下,根據頁面的大小, Scrapy 一秒能爬取40-70個頁面,一天在400萬到600萬頁面。也就是說 Scrapy 應付千萬級或者億級的爬取沒有問題。
- Scrapy 主要限制是select函數,在其他方面優化完美的情況下,大概有60%-70%的CPU花費在select上,剩下10%花費在框架本身。
- Scrapy 可以使用Windows下的IOCP或者Linux下的epoll機制。IOCP我試過,效果很一般,而且有很多鏈接出錯的情況,應該是Twisted本身對Windows支持的問題。據說epoll效果要好一些,我沒試過。
- Scrapy 支持續爬,在啟動的時候指定JOBDIR即可。JOBDIR實際原理是Scrapy在啟動的時候檢查是否設置了變量JOBDIR,如果設置了,則讀取該目錄的數據進行初始化。
- 續爬不是非常靠譜,只有使用Ctrl+C退出才能保證下次能續爬,如果不小心多按了一次Ctrl+C,沒有執行到收尾工作,有很大幾率下次續爬的時候會出問題。
- Scrapy本身沒有增量爬取的機制,這個得根據需求,自己實現。
- Python有一個MySQLdb庫,有一個函數executemany,開始以為這個函數是內部多次執行execute,后來實際測試發現不是。在大量插入數據的情況下,many函數的執行效率比execute高很多。
- Scrapy本身已經帶了URL去重。
- Scrapy不會執行class AJianSpider(BaseSpider)類的__DEL__。如果有在蜘蛛關閉的時候執行的收尾工作,可以使用擴展機制,在spider_closed中處理。
- Request有一個meta屬性,可以用於存儲和傳遞附加數據,實際是一個dict。
- 獲取鏈接建議用正則表達式,解析整個HTML非常耗時,哪怕使用最快的lxml,依然會比Python里的正則表達式慢四倍以上。而且還有大量的不規范HTML,處理起來很麻煩。正則的問題是會匹配到script里的網址,可以簡單總結一下遇到的不正常URL,過濾一下即可。
- 實際爬抓時,爬取國內網站會有卡住一段時間的情況,幾秒到十幾秒下載流量為幾k,過段時間恢復正常。爬取外國網站會有ConnectionLost的情況,原因不明。我采取的是比較暴力的方式,設置重試次數為1000次。或者修改一下代碼,Scrapy用的中間件處理的錯誤重試,可以修改retry.py的代碼,在多次重試失敗的情況下,把URL存儲到數據庫或文件中。
- Scrapy有一個比較坑的地方是二進制文件,Scrapy會爬取到二進制文件,Scrapy內置的二進制文件處理方式,是過濾擴展名,顯然不能滿足需求。Scrapy沒有一個只獲取URL HTTP頭的功能。如果在獲取URL的時候自己抓取HTTP頭獲取Content-Type會破壞twisted本身的機制,導致爬取異常緩慢。這里我的處理方法是寫了一個中間件,發送請求的時候過濾擴展名,如果擴展名在黑名單中,再自己獲取一下HTTP頭。如果文件類型真的是二進制文件則放棄請求。
- 中間件出現異常的時候Scrapy會直接退出,不會打印堆棧,寫中間件的時候可以先try住,在except主動打印異常。
- Scrapy自帶cProfile,分析性能很管用。
