作业:暂停和恢复爬网¶
有时,对于大型网站,最好暂停抓取,以便日后恢复。
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
。