Jobs: pausing and resuming crawls

有时,对于大型网站,希望暂停爬网并在以后能够恢复它们.

Scrapy通过提供以下功能来立即支持此功能:

  • 将计划的请求保留在磁盘上的调度程序
  • 一个重复的过滤器,可将访问的请求持久保存在磁盘上
  • 一种扩展,可在批次之间保持某些蜘蛛状态(键/值对)持久

Job directory

要启用持久性支持,您只需要通过JOBDIR设置定义作业目录 . 该目录将用于存储所有必需的数据,以保持单个作业的状态(即蜘蛛运行). 重要的是要注意,此目录不得由不同的Spider共享,甚至不能由同一Spider的不同作业/运行共享,因为该目录用于存储单个作业的状态.

How to use it

要启动启用了持久性支持的蜘蛛,请按以下方式运行它:

scrapy crawl somespider -s JOBDIR=crawls/somespider-1

然后,您可以随时安全地停止蜘蛛(通过按Ctrl-C或发送信号),并在以后通过发出相同的命令来恢复蜘蛛:

scrapy crawl somespider -s JOBDIR=crawls/somespider-1

Keeping persistent state between batches

有时,您可能希望在暂停/恢复批次之间保持一些持久的蜘蛛状态. 您可以spider.state使用spider.state属性,这应该是一个命令. 有一个内置的扩展程序,负责在启动和停止蜘蛛程序时从作业目录中序列化,存储和加载该属性.

这是使用蜘蛛状态的回调示例(为简便起见,省略了其他蜘蛛代码):

def parse_item(self, response):
    # parse item here
    self.state['items_count'] = self.state.get('items_count', 0) + 1

Persistence gotchas

如果您希望能够使用Scrapy持久性支持,请牢记以下几点:

Cookies expiration

Cookies可能会过期. 因此,如果您不快速恢复蜘蛛,计划的请求可能不再起作用. 如果您的蜘蛛不依赖Cookie,这将不是问题.

Request serialization

为了使持久性起作用,请求必须由pickle模块可序列化,因此您应确保请求可序列化.

这里最常见的问题是在无法lambda请求回调上使用lambda函数.

因此,例如,这将不起作用:

def some_callback(self, response):
    somearg = 'test'
    return scrapy.Request('http://www.example.com',
                          callback=lambda r: self.other_callback(r, somearg))

def other_callback(self, response, somearg):
    print("the argument passed is: %s" % somearg)

但这将:

def some_callback(self, response):
    somearg = 'test'
    return scrapy.Request('http://www.example.com',
                          callback=self.other_callback, cb_kwargs={'somearg': somearg})

def other_callback(self, response, somearg):
    print("the argument passed is: %s" % somearg)

如果您希望记录无法序列化的请求,则可以在项目的设置页面中将SCHEDULER_DEBUG设置设置为True . 默认情况下为False .