作业:暂停和恢复爬取

有时,对于大型网站,需要暂停爬取并在以后能够恢复它们。

Scrapy 通过提供以下功能,开箱即用地支持此功能

  • 一个将计划请求持久化到磁盘的调度器

  • 一个将已访问请求持久化到磁盘的去重过滤器

  • 一个扩展,用于在批次之间保持某些爬虫状态(键/值对)的持久性

作业目录

要启用持久化支持,请通过 JOBDIR 设置定义一个 作业目录

作业目录将存储所有必需的数据,以保持 单个 作业(即一次爬虫运行)的状态,以便如果干净地停止,以后可以恢复。

警告

此目录 能被不同的爬虫共享,甚至不能被同一爬虫的不同作业共享。

警告

对待作业目录应与对待 Scrapy 项目源代码一样谨慎。不要将 JOBDIR 指向不受信任方可写入的路径。

另请参阅 作业目录内容

如何使用

要启动一个启用持久化支持的爬虫,请像这样运行它

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

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

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

在批次之间保持持久状态

有时您需要在暂停/恢复批次之间保留一些持久的爬虫状态。您可以使用 spider.state 属性,它应该是一个字典。有一个 内置扩展,负责在爬虫启动和停止时,将该属性从作业目录序列化、存储和加载。

这是一个使用爬虫状态的回调示例(为简洁起见,省略了其他爬虫代码)

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

持久化注意事项

如果您想使用 Scrapy 的持久化支持,有几点需要记住

暂停限制

作业的暂停和恢复仅在爬虫干净停止时才受支持。强制、突然或以其他方式不干净的关闭可能导致作业目录中的数据损坏,这可能会阻止爬虫正确恢复。

Cookie 过期

Cookie 可能会过期。因此,如果您不尽快恢复爬虫,已计划的请求可能不再有效。如果您的爬虫不依赖 Cookie,这不会成为问题。

请求序列化

为了使持久化工作,Request 对象必须可以通过 pickle 进行序列化,但传递给其 __init__ 方法的 callbackerrback 值除外,它们必须是正在运行的 Spider 类的方​​法。

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

注意

由于请求是使用 pickle 序列化的,您存储在请求上的对象(例如其 cb_kwargsmeta 字典的值)在请求写入作业目录并随后从中读取时,会被深度复制。因此,回调会收到这些对象的 副本,而不是原始对象,对副本所做的更改不会反映在原始对象中。如果您依赖通过 cb_kwargsmeta 共享可变状态,请记住这一点。

作业目录内容

作业目录的内容取决于作业期间使用的组件。已知会写入作业目录的组件包括 调度器SpiderState 扩展。有关详细信息,请参阅相应组件的参考文档。

例如,在默认设置下,作业目录可能如下所示

├── requests.queue
|   ├── active.json
|   └── {hostname}-{hash}
|       └── {priority}{s?}
|           ├── q{00000}
|           └── info.json
├── requests.seen
└── spider.state

其中

  • Scheduler 创建 requests.queue/ 目录和 active.json 文件,后者包含上次作业暂停时由 DownloaderAwarePriorityQueue.close() 返回的状态数据。

  • DownloaderAwarePriorityQueue 创建 {hostname}-{hash} 目录。

  • ScrapyPriorityQueue 创建 {priority}{s?} 目录。

  • scrapy.squeues.PickleLifoDiskQueue,一个 queuelib.LifoDiskQueue 的子类,它使用 pickle 来序列化 scrapy.Request 对象的 dict 表示形式,创建 info.jsonq{00000} 文件。

  • RFPDupeFilter 创建 requests.seen 文件。

  • SpiderState 创建 spider.state 文件。