调度器

调度器组件接收来自引擎的请求,并将其存储到持久化和/或非持久化数据结构中。当引擎请求下载下一个请求时,它也会获取这些请求并将其反馈给引擎。

覆盖默认调度器

您可以通过在SCHEDULER 配置中提供自定义调度器类的完整 Python 路径来使用它。

最小调度器接口

class scrapy.core.scheduler.BaseScheduler[source]

调度器组件负责存储从引擎接收到的请求,并在需要时将其反馈(也返回给引擎)。

这些请求的原始来源包括:

  • 爬虫: start 方法,为 start_urls 属性中的 URL 创建的请求,请求回调

  • 爬虫中间件: process_spider_outputprocess_spider_exception 方法

  • 下载器中间件: process_request, process_responseprocess_exception 方法

调度器返回其存储请求(通过 next_request 方法)的顺序,在很大程度上决定了这些请求的下载顺序。请参阅 请求顺序

此类中定义的方法构成了 Scrapy 引擎将与之交互的最小接口。

close(reason: str) Deferred[None] | None[source]

当引擎关闭爬虫时调用。它接收抓取结束的原因作为参数,用于执行清理代码。

参数:

reason (str) – 描述爬虫关闭原因的字符串

abstract enqueue_request(request: Request) bool[source]

处理引擎接收到的请求。

如果请求存储成功,则返回 True,否则返回 False

如果为 False,引擎将触发 request_dropped 信号,并且不会在稍后时间再次尝试调度该请求。默认的 Scrapy 调度器在请求被去重过滤器拒绝时返回 False

classmethod from_crawler(crawler: Crawler) Self[source]

工厂方法,接收当前 Crawler 对象作为参数。

abstract has_pending_requests() bool[source]

如果调度器有排队的请求,则为 True,否则为 False

abstract next_request() Request | None[source]

返回下一个待处理的 Request 对象,如果当前没有准备好的请求,则返回 None

返回 None 意味着在当前 reactor 周期内不会将调度器中的请求发送给下载器。引擎将继续调用 next_request 直到 has_pending_requests 返回 False

open(spider: Spider) Deferred[None] | None[source]

当引擎打开爬虫时调用。它接收爬虫实例作为参数,用于执行初始化代码。

参数:

spider (Spider) – 当前抓取的爬虫对象

默认调度器

class scrapy.core.scheduler.Scheduler[source]

默认调度器。

请求存储在优先级队列(SCHEDULER_PRIORITY_QUEUE)中,这些队列根据 priority 对请求进行排序。

默认情况下,所有请求都使用一个基于内存的优先级队列。当使用 JOBDIR 时,还会创建一个基于磁盘的优先级队列,只有不可序列化的请求存储在基于内存的优先级队列中。对于给定的优先级值,内存中的请求优先于磁盘中的请求。

每个优先级队列将请求存储在单独的内部队列中,每个优先级值对应一个队列。内存优先级队列使用 SCHEDULER_MEMORY_QUEUE 队列,而磁盘优先级队列使用 SCHEDULER_DISK_QUEUE 队列。内部队列在请求优先级相同时决定 请求顺序。默认情况下,起始请求存储在单独的内部队列中,并且 排序方式不同

使用 DUPEFILTER_CLASS 的实例过滤重复请求。

请求顺序

默认设置下,待处理请求存储在 LIFO(后进先出)队列中(起始请求除外)。因此,抓取按 DFO(深度优先)顺序进行,这通常是最方便的抓取顺序。但是,您可以强制执行 BFO(广度优先)自定义顺序除了最初的几个请求)。

起始请求顺序

起始请求按照它们从 start() 方法中生成的顺序发送,并且在优先级相同时,起始请求优先于其他请求。

您可以将 SCHEDULER_START_MEMORY_QUEUESCHEDULER_START_DISK_QUEUE 设置为 None,以便在顺序和优先级方面像处理其他请求一样处理起始请求。

按 BFO 顺序抓取

如果您确实希望按 BFO(广度优先)顺序抓取,可以通过设置以下 配置来实现:

SCHEDULER_DISK_QUEUE = "scrapy.squeues.PickleFifoDiskQueue"
SCHEDULER_MEMORY_QUEUE = "scrapy.squeues.FifoMemoryQueue"

按自定义顺序抓取

您可以手动设置请求的 priority 来强制特定的请求顺序。

并发影响顺序

当待处理请求的数量低于 CONCURRENT_REQUESTS, CONCURRENT_REQUESTS_PER_DOMAINCONCURRENT_REQUESTS_PER_IP 的配置值时,这些请求会并发发送。

因此,抓取任务最初的几个请求可能不会遵循期望的顺序。将这些设置降低到 1 可以强制除了第一个请求之外的所有请求都按照期望的顺序执行,但这会显著降低整个抓取速度。

__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]

初始化调度器。

参数:
__len__() int[source]

返回排队的请求总数

close(reason: str) Deferred[None] | None[source]
  1. 如果存在磁盘队列,将待处理请求转储到磁盘

  2. 返回去重过滤器的 close 方法的结果

enqueue_request(request: Request) bool[source]

除非接收到的请求被去重过滤器过滤掉,否则尝试将其推入磁盘队列,如果失败则回退到内存队列。

增加相应的统计数据,例如:scheduler/enqueued, scheduler/enqueued/disk, scheduler/enqueued/memory

如果请求存储成功,则返回 True,否则返回 False

classmethod from_crawler(crawler: Crawler) Self[source]

工厂方法,接收当前 Crawler 对象作为参数。

has_pending_requests() bool[source]

如果调度器有排队的请求,则为 True,否则为 False

next_request() Request | None[source]

从内存队列中返回一个 Request 对象,如果内存队列为空,则回退到磁盘队列。如果没有更多排队的请求,则返回 None

增加相应的统计数据,例如:scheduler/dequeued, scheduler/dequeued/disk, scheduler/dequeued/memory

open(spider: Spider) Deferred[None] | None[source]
  1. 初始化内存队列

  2. 如果 jobdir 属性是一个有效目录,则初始化磁盘队列

  3. 返回去重过滤器的 open 方法的结果