Scrapy Spider 完成网页抓取后无法终止

Jer*_*dan 5 python scrapy web-scraping scrapy-spider

我正在用 Scrapy 运行一个蜘蛛,但在它完成爬行后,它似乎无法终止。日志统计只是递归地报告它正在抓取 0 页/分钟。当我尝试使用 Ctrl-C 退出时,它无法正常关闭,我必须再次使用 Ctrl-C 强制退出。任何线索发生了什么?

完成刮擦后,我只是得到这样的输出:

2017-08-24 11:13:45 [scrapy.extensions.logstats] 信息:抓取 60 页(以 0 页/分钟),抓取 54 个项目(以 0 项/分钟)

2017-08-24 11:14:45 [scrapy.extensions.logstats] 信息:抓取 60 页(以 0 页/分钟),抓取 54 个项目(以 0 项/分钟)

2017-08-24 11:15:45 [scrapy.extensions.logstats] 信息:抓取 60 页(以 0 页/分钟),抓取 54 个项目(以 0 项/分钟)

2017-08-24 11:16:45 [scrapy.extensions.logstats] 信息:抓取 60 页(以 0 页/分钟),抓取 54 个项目(以 0 项/分钟)

2017-08-24 11:17:45 [scrapy.extensions.logstats] 信息:抓取 60 页(以 0 页/分钟),抓取 54 个项目(以 0 项/分钟)

2017-08-24 11:18:45 [scrapy.extensions.logstats] 信息:抓取 60 页(以 0 页/分钟),抓取 54 个项目(以 0 项/分钟)

2017-08-24 11:19:45 [scrapy.extensions.logstats] 信息:抓取 60 页(以 0 页/分钟),抓取 54 个项目(以 0 项/分钟)

2017-08-24 11:20:45 [scrapy.extensions.logstats] 信息:抓取 60 页(以 0 页/分钟),抓取 54 个项目(以 0 项/分钟)

2017-08-24 11:21:45 [scrapy.extensions.logstats] 信息:抓取 60 页(以 0 页/分钟),抓取 54 个项目(以 0 个项目/分钟)

无限期地继续下去。

我的蜘蛛转到一个页面,该页面包含多个页面上的链接列表。它访问第一页,提取链接(使用请求元技巧在跟随链接的同时传递一些信息),然后转到链接的下一页。

第二个解析器从各个页面中提取信息。

我没有看到任何错误消息,并且作业成功执行;它只是无法结束。这是一个问题,因为我想使用脚本来调用作业在不同的页面上多次运行(相同的结构,不同的信息),但是由于第一个作业从未完成,我永远无法进入下一组要抓取的页面。

parse(self, response)方法产生两种类型的信息。

  1. 对于页面上的每个链接,请访问该页面以提取更多信息。

    request = scrapy.Request(item['url'], callback=self.parse_transcript)
    request.meta['item'] = item
    yield request
    
    Run Code Online (Sandbox Code Playgroud)
  2. 如果还有另一页链接,请使用正则表达式获取链接并将页码加 1。

    while data['count'] > 0:
        next_page = re.sub('(?<=page=)(\d+)', lambda x: str(int(x.group(0)) + 1), response.url) 
        yield Request(next_page)
    
    Run Code Online (Sandbox Code Playgroud)

编辑 1:多亏了一个建议,我使用 telnet 扩展检查了引擎状态。我不确定如何解释这些信息。

>>> est()
Execution engine status

time()-engine.start_time                        : 10746.1215799
engine.has_capacity()                           : False
len(engine.downloader.active)                   : 0
engine.scraper.is_idle()                        : False
engine.spider.name                              : transcripts
engine.spider_is_idle(engine.spider)            : False
engine.slot.closing                             : <Deferred at 0x10d8fda28>
len(engine.slot.inprogress)                     : 4
len(engine.slot.scheduler.dqs or [])            : 0
len(engine.slot.scheduler.mqs)                  : 0
len(engine.scraper.slot.queue)                  : 0
len(engine.scraper.slot.active)                 : 4
engine.scraper.slot.active_size                 : 31569
engine.scraper.slot.itemproc_size               : 0
engine.scraper.slot.needs_backout()             : False
Run Code Online (Sandbox Code Playgroud)

编辑 2:我尝试在蜘蛛到达链接末尾后引发异常以关闭蜘蛛,但这过早地阻止了蜘蛛能够访问所有被废弃的链接。此外,关闭蜘蛛后,发动机似乎仍然挂起。

while data['count'] > 0:
    next_page = re.sub('(?<=page=)(\d+)', lambda x: str(int(x.group(0)) + 1), response.url)
    yield Request(next_page)
else:
    raise CloseSpider('End of transcript history has been reached.')
Run Code Online (Sandbox Code Playgroud)

编辑 3:我也尝试使用 CLOSESPIDER_TIMEOUT 扩展,但无济于事。蜘蛛似乎正确关闭,但发动机仍然无限期地空转。

2017-08-30 11:20:44 [scrapy.extensions.logstats] 信息:抓取 48 页(9 页/分钟),抓取 42 项(9 项/分钟)

2017-08-30 11:23:44 [scrapy.extensions.logstats] 信息:抓取 48 页(以 0 页/分钟),抓取 42 个项目(以 0 项/分钟)

2017-08-30 11:24:44 [scrapy.extensions.logstats] 信息:抓取 48 页(0 页/分钟),抓取 42 个项目(0 项/分钟)

2017-08-30 11:25:44 [scrapy.core.engine] 信息:关闭蜘蛛(closespider_timeout)

2017-08-30 11:25:44 [scrapy.extensions.logstats] 信息:抓取 48 页(以 0 页/分钟),抓取 42 个项目(以 0 项/分钟)

2017-08-30 11:28:44 [scrapy.extensions.logstats] 信息:抓取 48 页(0 页/分钟),抓取 42 个项目(0 项/分钟)

2017-08-30 11:29:44 [scrapy.extensions.logstats] 信息:抓取 48 页(0 页/分钟),抓取 42 个项目(0 项/分钟)

2017-08-30 11:32:44 [scrapy.extensions.logstats] 信息:抓取 48 页(0 页/分钟),抓取 42 个项目(0 项/分钟)

^C2017-08-30 11:33:31 [scrapy.crawler] INFO:收到 SIGINT,正常关闭。再次发送强制

2017-08-30 11:41:44 [scrapy.extensions.logstats] 信息:抓取 48 页(0 页/分钟),抓取 42 个项目(0 项/分钟)

^C2017-08-30 11:45:52 [scrapy.crawler] INFO:收到两次 SIGINT,强制不正常关机