scrapy-redis所有request爬取完畢,如何解決爬蟲空跑問題?
阿新 • • 發佈:2018-11-21
scrapy-redis所有request爬取完畢,如何解決爬蟲空跑問題?
1. 背景
根據scrapy-redis分散式爬蟲的原理,多臺爬蟲主機共享一個爬取佇列。當爬取佇列中存在request時,爬蟲就會取出request進行爬取,如果爬取佇列中不存在request時,爬蟲就會處於等待狀態,行如下:
E:\Miniconda\python.exe E:/PyCharmCode/redisClawerSlaver/redisClawerSlaver/spiders/main.py 2017-12-12 15:54:18 [scrapy.utils.log] INFO: Scrapy 1.4.0 started (bot: scrapybot) 2017-12-12 15:54:18 [scrapy.utils.log] INFO: Overridden settings: {'SPIDER_LOADER_WARN_ONLY': True} 2017-12-12 15:54:18 [scrapy.middleware] INFO: Enabled extensions: ['scrapy.extensions.corestats.CoreStats', 'scrapy.extensions.telnet.TelnetConsole', 'scrapy.extensions.logstats.LogStats'] 2017-12-12 15:54:18 [myspider_redis] INFO: Reading start URLs from redis key 'myspider:start_urls' (batch size: 110, encoding: utf-8 2017-12-12 15:54:18 [scrapy.middleware] INFO: Enabled downloader middlewares: ['scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware', 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware', 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware', 'redisClawerSlaver.middlewares.ProxiesMiddleware', 'redisClawerSlaver.middlewares.HeadersMiddleware', 'scrapy.downloadermiddlewares.retry.RetryMiddleware', 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware', 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware', 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware', 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware', 'scrapy.downloadermiddlewares.stats.DownloaderStats'] 2017-12-12 15:54:18 [scrapy.middleware] INFO: Enabled spider middlewares: ['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware', 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware', 'scrapy.spidermiddlewares.referer.RefererMiddleware', 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware', 'scrapy.spidermiddlewares.depth.DepthMiddleware'] 2017-12-12 15:54:18 [scrapy.middleware] INFO: Enabled item pipelines: ['redisClawerSlaver.pipelines.ExamplePipeline', 'scrapy_redis.pipelines.RedisPipeline'] 2017-12-12 15:54:18 [scrapy.core.engine] INFO: Spider opened 2017-12-12 15:54:18 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min) 2017-12-12 15:55:18 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min) 2017-12-12 15:56:18 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
- 可是,如果所有的request都已經爬取完畢了呢?這件事爬蟲程式是不知道的,它無法區分結束和空窗期狀態的不同,所以會一直處於上面的那種等待狀態,也就是我們說的空跑。
- 那有沒有辦法讓爬蟲區分這種情況,自動結束呢?
2. 環境
- 系統:win7
- scrapy-redis
- redis 3.0.5
- python 3.6.1
3. 解決方案
- 從背景介紹來看,基於scrapy-redis分散式爬蟲的原理,爬蟲結束是一個很模糊的概念,在爬蟲爬取過程中,爬取佇列是一個不斷動態變化的過程,隨著request的爬取,又會有新的request進入爬取佇列。進進出出。爬取速度高於填充速度,就會有佇列空窗期(爬取佇列中,某一段時間會出現沒有request的情況),爬取速度低於填充速度,就不會出現空窗期。
- 所以,下面這兩種方案都是一種大概的思路。
3.1. 利用scrapy的關閉spider擴充套件功能
# 關閉spider擴充套件 class scrapy.contrib.closespider.CloseSpider 當某些狀況發生,spider會自動關閉。每種情況使用指定的關閉原因。 關閉spider的情況可以通過下面的設定項配置: CLOSESPIDER_TIMEOUT CLOSESPIDER_ITEMCOUNT CLOSESPIDER_PAGECOUNT CLOSESPIDER_ERRORCOUNT
- CLOSESPIDER_TIMEOUT
CLOSESPIDER_TIMEOUT
預設值: 0
一個整數值,單位為秒。如果一個spider在指定的秒數後仍在執行, 它將以 closespider_timeout 的原因被自動關閉。 如果值設定為0(或者沒有設定),spiders不會因為超時而關閉。
- CLOSESPIDER_ITEMCOUNT
CLOSESPIDER_ITEMCOUNT
預設值: 0
一個整數值,指定條目的個數。如果spider爬取條目數超過了指定的數, 並且這些條目通過item pipeline傳遞,spider將會以 closespider_itemcount 的原因被自動關閉。
- CLOSESPIDER_PAGECOUNT
CLOSESPIDER_PAGECOUNT
0.11 新版功能.
預設值: 0
一個整數值,指定最大的抓取響應(reponses)數。 如果spider抓取數超過指定的值,則會以 closespider_pagecount 的原因自動關閉。 如果設定為0(或者未設定),spiders不會因為抓取的響應數而關閉。
- CLOSESPIDER_ERRORCOUNT
CLOSESPIDER_ERRORCOUNT
0.11 新版功能.
預設值: 0
一個整數值,指定spider可以接受的最大錯誤數。 如果spider生成多於該數目的錯誤,它將以 closespider_errorcount 的原因關閉。 如果設定為0(或者未設定),spiders不會因為發生錯誤過多而關閉。
- 示例:開啟 settings.py,新增一個配置項,如下
# 爬蟲執行超過23.5小時,如果爬蟲還沒有結束,則自動關閉
CLOSESPIDER_TIMEOUT = 84600
- 特別注意:如果爬蟲在規定時限沒有把request全部爬取完畢,此時強行停止的話,爬取佇列中就還會存有部分request請求。那麼爬蟲下次開始爬取時,一定要記得在master端對爬取佇列進行清空操作。
- 另外如果是分散式爬蟲,先確認幾臺機器同時跑,拿CLOSESPIDER_ITEMCOUNT來說,比如要拿100條資料,10臺機器一起跑,那麼CLOSESPIDER_ITEMCOUNT=10即可
第二種方案:改scrapy_redis的原始碼,不適合分散式部署