Scrapy作业:暂停与继续爬取
抓取大型网站时,有时希望暂停爬取,并在之后继续。
Scrapy通过以下内置机制支持这一功能:
- 将已调度的请求持久化到磁盘的调度器。
- 将已访问请求持久化到磁盘的去重过滤器。
- 在批次之间持久保存部分爬虫状态(键值对)的扩展。
作业目录
要启用持久化支持,通过JOBDIR设置指定一个作业目录。
这个目录保存维持单个作业(即一次爬虫运行)状态所需的全部数据,因此只要正常停止,稍后就可以继续运行。
另见作业目录的内容。
如何使用
要启动启用持久化支持的爬虫,运行:
scrapy crawl somespider -s JOBDIR=crawls/somespider-1
此后可以随时安全停止爬虫(按Ctrl-C或发送信号),之后再次执行相同的命令即可继续:
scrapy crawl somespider -s JOBDIR=crawls/somespider-1
根据爬虫名称生成作业目录
将不同作业目录分开的方法之一,是在scrapy.Spider.update_settings()中构建路径,让一组爬虫使用除爬虫名称之外均相同的路径:
from pathlib import Path
from scrapy import Spider
class BaseSpider(Spider):
@classmethod
def update_settings(cls, settings):
super().update_settings(settings)
settings.set("JOBDIR", str(Path("crawls", cls.name)), priority="spider")
在暂停和继续运行的批次之间保存状态
有时需要在暂停与继续运行的批次之间持久保存爬虫状态。为此可使用spider.state属性,其值应为字典。Scrapy有一个内置扩展:在爬虫启动和停止时,负责将该属性序列化、存储到作业目录,以及从目录加载。
下面是使用爬虫状态的回调示例,其他爬虫代码为简洁起见省略:
def parse_item(self, response):
# parse item here
self.state["items_count"] = self.state.get("items_count", 0) + 1
持久化的注意事项
使用Scrapy的持久化支持时,需要注意以下事项。
暂停的限制
只有通过正常停止爬虫来暂停时,才支持暂停与继续。强制、突然或其他非正常关闭可能使作业目录中的数据损坏,导致爬虫无法正确继续运行。
Scrapy版本变化
作业目录的内容属于写入该目录的Scrapy版本的实现细节。继续作业时必须使用暂停作业时的同一个Scrapy版本;升级或降级Scrapy后,应使用新的作业目录启动新作业。
Cookie过期
Cookie可能过期,因此如果没有很快恢复爬虫,已调度的请求可能不再有效。如果爬虫不依赖Cookie,就不会有这个问题。
请求序列化
要实现持久化,scrapy.Request对象必须可以通过pickle序列化,但传入其__init__方法的callback与errback值除外:它们必须是正在运行的scrapy.Spider类的方法。
无法序列化的请求只保存在内存中:它们仍会被发送,但暂停爬取时会丢失。
如果希望记录无法序列化的请求,可以在项目设置中将SCHEDULER_DEBUG设为True,其默认值为False。
作业目录的内容
作业目录的内容取决于作业所使用的组件。已知会写入该目录的组件包括调度器和scrapy.extensions.spiderstate.SpiderState扩展。详细信息请参阅相应组件的参考文档。
例如在默认设置下,作业目录可能如下所示:
├── requests.queue
| ├── active.json
| └── {hostname}-{hash}
| └── {priority}{s?}
| ├── q{00000}
| └── info.json
├── requests.seen
└── spider.state
其中:
scrapy.core.scheduler.Scheduler创建requests.queue/目录与active.json文件。后者保存上一次暂停作业时DownloaderAwarePriorityQueue.close()返回的状态数据。scrapy.pqueues.DownloaderAwarePriorityQueue创建{hostname}-{hash}目录。scrapy.pqueues.ScrapyPriorityQueue创建{priority}{s?}目录。scrapy.squeues.PickleFifoDiskQueue是queuelib.FifoDiskQueue的子类,使用pickle序列化scrapy.Request对象的dict表示,并创建info.json与q{00000}文件。scrapy.dupefilters.RFPDupeFilter创建requests.seen文件。scrapy.extensions.spiderstate.SpiderState扩展创建spider.state文件。
来源与许可
来源:Scrapy官方文档:Jobs: pausing and resuming crawls,Scrapy开发者。本版为中文翻译。项目版权与BSD许可见官方LICENSE;完整版权、条件与免责声明随来源文件保留。











暂无评论内容