调度器
调度器组件从引擎接收请求,并将其存储到持久化和/或非持久化数据结构中。当引擎要求下载下一个请求时,它还会获取这些请求并将其反馈给引擎。
重写默认调度器
您可以通过在SCHEDULER设置中提供自定义调度器类的完整 Python 路径来使用它。
最小调度器接口
- class scrapy.core.scheduler.BaseScheduler[source]
调度器组件负责存储从引擎接收到的请求,并根据请求将其(也)反馈给引擎。
所述请求的原始来源是
Spider:
start方法,为start_urls属性中的 URL 创建的请求,请求回调Spider middleware:
process_spider_output和process_spider_exception方法Downloader middleware:
process_request,process_response和process_exception方法
调度器返回其存储请求(通过
next_request方法)的顺序在决定这些请求的下载顺序方面起着重要作用。参见 请求顺序。此课程中定义的方法构成了 Scrapy 引擎将与之交互的最小接口。
- close(reason: str) Deferred[None] | None[source]
当引擎关闭爬虫时调用。它接收爬取完成的原因作为参数,可用于执行清理代码。
- 参数:
reason (
str) – 描述爬虫关闭原因的字符串
- abstractmethod enqueue_request(request: Request) bool[source]
处理引擎收到的请求。
如果请求正确存储,返回
True,否则返回False。如果为
False,引擎将触发request_dropped信号,并且不会在以后再次尝试调度该请求。作为参考,当请求被去重过滤器拒绝时,默认的 Scrapy 调度器返回False。
默认调度器
- class scrapy.core.scheduler.Scheduler[source]
默认调度器。
请求存储在优先级队列(
SCHEDULER_PRIORITY_QUEUE)中,这些队列根据priority对请求进行排序。默认情况下,所有请求都使用基于内存的优先级队列。当使用
JOBDIR时,也会创建基于磁盘的优先级队列,并且只有不可序列化的请求才存储在基于内存的优先级队列中。对于给定的优先级值,内存中的请求优先于磁盘中的请求。每个优先级队列将请求存储在单独的内部队列中,每个优先级值一个队列。内存优先级队列使用
SCHEDULER_MEMORY_QUEUE队列,而磁盘优先级队列使用SCHEDULER_DISK_QUEUE队列。当请求具有相同优先级时,内部队列决定请求顺序。默认情况下,起始请求存储在单独的内部队列中,并且排序方式不同。重复的请求通过
DUPEFILTER_CLASS的实例进行过滤。请求顺序
在默认设置下,待处理的请求存储在 LIFO 队列中(起始请求除外)。因此,爬取以 DFO 顺序进行,这通常是最方便的爬取顺序。但是,您可以强制使用 BFO 或 自定义顺序(除了最初的几个请求)。
起始请求顺序
起始请求按照它们从
start()生成的顺序发送,并且在具有相同priority的情况下,其他请求优先于起始请求。您可以将
SCHEDULER_START_MEMORY_QUEUE和SCHEDULER_START_DISK_QUEUE设置为None,以便在处理起始请求的顺序和优先级时与其他请求相同。以 BFO 顺序爬取
如果您确实想以 BFO 顺序爬取,可以通过设置以下设置来实现
DEPTH_PRIORITY=1SCHEDULER_DISK_QUEUE="scrapy.squeues.PickleFifoDiskQueue"SCHEDULER_MEMORY_QUEUE="scrapy.squeues.FifoMemoryQueue"以自定义顺序爬取
您可以手动设置请求的
priority以强制执行特定的请求顺序。并发影响顺序
当待处理请求低于
CONCURRENT_REQUESTS或CONCURRENT_REQUESTS_PER_DOMAIN的配置值时,这些请求将并发发送。因此,爬取的最初几个请求可能不会遵循预期的顺序。将这些设置降低到
1会强制执行所需的顺序(除了第一个请求),但这会显著减慢整个爬取过程。作业目录内容
警告
此类在 作业目录 中生成的文件是实现细节,在 Scrapy 的未来版本中可能会在没有警告的情况下发生变化。请勿将以下信息用于调试目的以外的任何用途。
当使用
JOBDIR时,此调度器类在 作业目录 内创建一个名为
requests.queue的目录,用于跟踪调度器中存储的所有请求(即尚未下载的请求)。在该目录内生成一个
active.json文件,其中包含SCHEDULER_PRIORITY_QUEUE状态(startprios)的 JSON 表示。该文件在作业停止(干净地)时生成,并在恢复作业时加载。
实例化配置的
SCHEDULER_PRIORITY_QUEUE,其中requests.queue/作为持久化目录 (key),SCHEDULER_DISK_QUEUE作为 downstream_queue_cls。优先级队列可以直接或通过SCHEDULER_DISK_QUEUE的实例在该目录内创建额外的文件和目录。
此调度器类还使用配置的
DUPEFILTER_CLASS,它也可能在作业目录内写入数据。- __init__(dupefilter: BaseDupeFilter, jobdir: str | None = None, dqclass: type[BaseQueue] | None = None, mqclass: type[BaseQueue] | None = None, logunser: bool = False, stats: StatsCollector | None = None, pqclass: type[ScrapyPriorityQueue] | None = None, crawler: Crawler | None = None)[source]
初始化调度器。
- 参数:
dupefilter (
scrapy.dupefilters.BaseDupeFilter实例或类似:任何实现 BaseDupeFilter 接口的类) – 负责检查和过滤重复请求的对象。默认使用DUPEFILTER_CLASS设置的值。jobdir (
str或None) – 用于持久化爬取状态的目录路径。默认使用JOBDIR设置的值。参见 作业:暂停和恢复爬取。dqclass (class) – 用作持久化请求队列的类。默认使用
SCHEDULER_DISK_QUEUE设置的值。mqclass (class) – 用作非持久化请求队列的类。默认使用
SCHEDULER_MEMORY_QUEUE设置的值。logunser (bool) – 一个布尔值,指示是否应记录不可序列化的请求。默认使用
SCHEDULER_DEBUG设置的值。stats (
scrapy.statscollectors.StatsCollector实例或类似:任何实现 StatsCollector 接口的类) – 一个统计收集器对象,用于记录请求调度过程的统计信息。默认使用STATS_CLASS设置的值。pqclass (class) – 用作请求优先级队列的类。默认使用
SCHEDULER_PRIORITY_QUEUE设置的值。crawler (
scrapy.crawler.Crawler) – 对应于当前爬取的爬虫对象。
- enqueue_request(request: Request) bool[source]
除非收到的请求被去重过滤器过滤掉,否则尝试将其推入磁盘队列,如果失败则回退到推入内存队列。
增加相应的统计信息,例如:
scheduler/enqueued、scheduler/enqueued/disk、scheduler/enqueued/memory。如果请求成功存储,返回
True,否则返回False。
优先级队列
- class scrapy.pqueues.DownloaderAwarePriorityQueue(crawler: Crawler, downstream_queue_cls: type[QueueProtocol], key: str, slot_startprios: dict[str, Iterable[int]] | None = None, *, start_queue_cls: type[QueueProtocol] | None = None)[source]
此优先级队列考虑下载器活动:具有最少活跃下载量的域(槽位)会首先出队。
磁盘持久化
警告
此类在磁盘上生成的文件是实现细节,在 Scrapy 的未来版本中可能会在没有警告的情况下发生变化。请勿将以下信息用于调试目的以外的任何用途。
当组件使用非空 key 参数实例化此课程时,key 将用作持久化目录,并且在该目录内,此类为每个下载槽(域)创建一个子目录。
这些子目录以对应的下载槽命名,其中不安全的路径字符被下划线替换,并附加 MD5 散列后缀以避免冲突。
对于每个下载槽,此课程会创建一个
ScrapyPriorityQueue实例,其中下载槽子目录作为 key,并使用其自身的 downstream_queue_cls。
- class scrapy.pqueues.ScrapyPriorityQueue(crawler: Crawler, downstream_queue_cls: type[QueueProtocol], key: str, startprios: Iterable[int] = (), *, start_queue_cls: type[QueueProtocol] | None = None)[source]
一个使用多个内部队列(通常是 FIFO 队列)实现的优先级队列。它为每个优先级值使用一个内部队列。内部队列必须实现以下方法:
push(obj)
pop()
close()
__len__()
可选地,队列可以提供一个
peek方法,该方法应返回pop将返回的下一个对象,但不会将其从队列中移除。ScrapyPriorityQueue 的
__init__方法接收一个 downstream_queue_cls 参数,该参数是一个类,用于在分配新优先级时实例化一个新的(内部)队列。只应使用整数优先级。数字越小,优先级越高。
startprios 是一个起始优先级序列。如果队列之前关闭时留下了一些非空的优先级桶,则应在 startprios 中传递这些优先级。
磁盘持久化
警告
此类在磁盘上生成的文件是实现细节,在 Scrapy 的未来版本中可能会在没有警告的情况下发生变化。请勿将以下信息用于调试目的以外的任何用途。
当组件使用非空 key 参数实例化此课程时,key 将用作持久化目录。
对于每个入队的请求,此课程会检查
对于上述每个组合,此类都会创建一个 downstream_queue_cls(如果是起始请求且已传入 start_queue_cls,则创建 start_queue_cls)的实例,其中 key 设置为持久化目录的一个子目录,该子目录以请求优先级的负值命名(例如
-1),如果是一个起始请求,则带有s后缀(例如-1s)。