Skip to main content

作业:暂停和恢复爬网

有时,对于大型网站,最好暂停抓取,以便日后恢复。

Scrapy通过提供以下设施支持这种功能:

  • 在磁盘上保留调度请求的调度程序

  • 重复过滤器,用于在磁盘上保留访问的请求

  • 一个扩展,保持一些蜘蛛状态(键/值对)在批次之间持久

作业目录

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

如何使用它

要启动启用了持久性支持的蜘蛛,请按如下所示运行:

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

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

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

在批处理之间保持持久状态

有时你会想要在暂停/恢复批处理之间保持一些持续的蜘蛛状态。你可以使用 spider.state 属性,应该是一个dict。有一个内置的扩展,当蜘蛛启动和停止时,它负责从作业目录中序列化,存储和加载该属性。

这里是一个使用蜘蛛状态的回调的示例(为了简洁省略其他蜘蛛代码):

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

持久性陷阱

如果您想要使用Scrapy持久性支持,请记住以下几点:

Cookie到期

Cookie可能过期。所以,如果你不快速恢复你的蜘蛛,预定的请求可能不再工作。这不会是一个问题,如果你的蜘蛛不依赖于Cookie。

请求序列化

请求必须可以由 pickle 模块序列化,以使持久性工作,因此您应该确保您的请求是可序列化的。

这里最常见的问题是对请求回调使用不能持久化的 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:", somearg

但这会的:

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

def other_callback(self, response):
    somearg = response.meta['somearg']
    print "the argument passed is:", somearg

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