如何改造 Scrapy 從而實現多網站大規模爬取?
Scrapy 框架默認是用來開發定向爬蟲的。一般情況下,在 spiders 文件夾下面的一個.py 文件對應了一個網站的爬取。
但還有另外一種爬蟲,它不會拘泥于提取頁面上的特定文字,而是關注如何并行爬取非常多的網站。這種爬蟲可以實現大規模的爬取。這種爬蟲,一般是從若干個種子網址開始爬。進入每個網址后,把該頁面的所有網址作為新的種子網址繼續爬取,源源不斷,生生不息。但爬到以后,一般直接把整個頁面的源代碼保存下來,通過 Kafka 或者其他組件傳給另外的服務進行解析。
為了讓 Scrapy 適配這種通用的解析邏輯,需要做一些定制化修改。Scrapy 官方文檔中,給出了幾點修改建議。
修改調度隊列
Scrapy 默認的調度隊列是scrapy.pqueues.ScrapyPriorityQueue,它適合做定向爬蟲使用,對于通用爬蟲,我們應該修改為scrapy.pqueues.DownloaderAwarePriorityQueue。在 settings.py文件中添加一行:
- SCHEDULER_PRIORITY_QUEUE = 'scrapy.pqueues.DownloaderAwarePriorityQueue'
提高并發量在
settings.py中增加配置:
- CONCURRENT_REQUESTS = 100
- CONCURRENT_REQUESTS_PER_DOMAIN = 100
但是并發量實際上受內存和 CPU 的限制,建議實際測試,選擇最適合的數字。
提高 Twisted IO 線程池大小
Scrapy 在做 DNS 解析的時候,是阻塞式的。所以請求量越高,解析 DNS 就會越慢。為了避免這個情況,可以提高線程池的大小。在 settings.py中增加一個配置:
- REACTOR_THREADPOOL_MAXSIZE = 20
搭建專用 DNS 服務器
如果爬蟲進程數太多,并發又太快,可能會對 DNS 服務器形成 Dos 攻擊。所以建議自己單獨搭建一個 DNS 服務器。
減少日志量
Scrapy 默認是 DEBUG 級別的日志等級,每次爬取會產生大量的日志。通過把日志等級調整到INFO 可以大大減少日志量。在 settings.py 中增加一行:
- LOG_LEVEL = 'INFO'
禁用 Cookies 和自動重試
大規模爬蟲一般不需要用到 Cookies,所以可以把它禁用。請求失敗的自動重試會降低爬蟲的速度。但是由于大規模爬蟲的爬取范圍很大,對于個別失敗的請求沒有必要重試。因此修改settings.py:
- COOKIES_ENABLED = False
- RETRY_ENABLED = False
降低請求超時時間,禁用自動跳轉
有些網址因為遠在大洋彼岸或者受到了干擾,請求響應時間很長。對于這種網址,應該果斷放棄,避免影響其他網址的爬取。
禁用自動跳轉功能,也有助于提高網頁訪問速度。
- DOWNLOAD_TIMEOUT = 10
- REDIRECT_ENABLED = False
使用廣度有限搜索
Scrapy 默認基于深度優先(DFO)搜索算法。但在大規模爬蟲中,我們一般會使用廣度有限(BFO)搜索算法:
- DEPTH_PRIORITY = 1
- SCHEDULER_DISK_QUEUE = 'scrapy.squeues.PickleFifoDiskQueue'
- SCHEDULER_MEMORY_QUEUE = 'scrapy.squeues.FifoMemoryQueue'
關注內存,謹防內存泄露如果你發現爬蟲占用大量內存,但是速度遠遠低于你設置的并發速度,那么要考慮是否發生了內存泄露。