Spider 中间件

Spider 中间件是一个框架,它提供了钩子进入 Scrapy 的 Spider 处理机制,您可以在其中插入自定义功能来处理发送到Spider进行处理的响应,以及处理从 Spider 生成的请求和项目。

激活 Spider 中间件

要激活 Spider 中间件组件,请将其添加到SPIDER_MIDDLEWARES 设置中,该设置是一个字典,其键是中间件类路径,其值是中间件顺序。

以下是一个示例

SPIDER_MIDDLEWARES = {
    "myproject.middlewares.CustomSpiderMiddleware": 543,
}

SPIDER_MIDDLEWARES 设置与 Scrapy 中定义的 SPIDER_MIDDLEWARES_BASE 设置合并,然后按顺序排序以获得最终排序的启用中间件列表:第一个中间件是最靠近引擎的,最后一个是最靠近 Spider 的。换句话说,每个中间件的 process_spider_input() 方法将按中间件顺序递增(100、200、300、…)调用,而每个中间件的 process_spider_output() 方法将按顺序递减调用。

要决定为中间件分配哪个顺序,请查看 SPIDER_MIDDLEWARES_BASE 设置并根据要插入中间件的位置选择一个值。顺序很重要,因为每个中间件执行不同的操作,并且您的中间件可能依赖于某些先前(或后续)中间件的应用。

如果要禁用内置中间件(在 SPIDER_MIDDLEWARES_BASE 中定义并默认启用),则必须在您的项目 SPIDER_MIDDLEWARES 设置中定义它并将 None 作为其值。例如,如果要禁用 off-site 中间件

SPIDER_MIDDLEWARES = {
    "scrapy.spidermiddlewares.referer.RefererMiddleware": None,
    "myproject.middlewares.CustomRefererSpiderMiddleware": 700,
}

最后,请记住,某些中间件可能需要通过特定设置启用。有关更多信息,请参阅每个中间件文档。

编写自己的 Spider 中间件

每个 Spider 中间件都是一个 Python 类,它定义了一个或多个下面定义的方法。

主要入口点是 from_crawler 类方法,它接收一个 Crawler 实例。例如,Crawler 对象使您可以访问 设置

class scrapy.spidermiddlewares.SpiderMiddleware
process_spider_input(response, spider)

此方法对通过 Spider 中间件并进入 Spider 进行处理的每个响应调用。

process_spider_input() 应返回 None 或引发异常。

如果它返回 None,Scrapy 将继续处理此响应,执行所有其他中间件,直到最终将响应交给 Spider 进行处理。

如果它引发异常,Scrapy 将不会调用任何其他 Spider 中间件 process_spider_input(),并将调用请求错误回调(如果有),否则将启动 process_spider_exception() 链。错误回调的输出将反向链接到其他方向,以便 process_spider_output() 处理它,或者如果它引发异常,则调用 process_spider_exception()

参数:
  • response (Response 对象) – 正在处理的响应

  • spider (Spider 对象) – 此响应的目标 Spider

process_spider_output(response, result, spider)

在 Spider 处理响应后,使用 Spider 返回的结果调用此方法。

process_spider_output() 必须返回一个 Request 对象和 项目对象 的可迭代对象。

2.7 版中的更改: 此方法可以定义为 异步生成器,在这种情况下,result 是一个 异步可迭代对象

考虑将此方法定义为 异步生成器,这将是 Scrapy 未来版本的要求。但是,如果您计划与其他人共享您的 Spider 中间件,请考虑 强制 Scrapy 2.7 作为 Spider 中间件的最低要求,或者 使您的 Spider 中间件通用,以便它适用于早于 Scrapy 2.7 的 Scrapy 版本。

参数:
  • response (Response 对象) – 生成 Spider 此输出的响应

  • result (Request 对象和 项目对象 的可迭代对象) – Spider 返回的结果

  • spider (Spider 对象) – 正在处理其结果的 Spider

process_spider_output_async(response, result, spider)

2.7 版中的新功能。

如果定义了,此方法必须是一个异步生成器,如果 result 是一个异步可迭代对象,则会调用它而不是process_spider_output()

process_spider_exception(response, exception, spider)

当蜘蛛或process_spider_output() 方法(来自之前的蜘蛛中间件)引发异常时,会调用此方法。

process_spider_exception() 应该返回 None 或一个 Requestitem 对象的可迭代对象。

如果它返回 None,Scrapy 将继续处理此异常,执行后续中间件组件中的任何其他 process_spider_exception(),直到没有剩余的中间件组件,并且异常到达引擎(在引擎中记录并丢弃)。

如果它返回一个可迭代对象,则process_spider_output() 管道从下一个蜘蛛中间件开始启动,并且不会调用其他 process_spider_exception()

参数:
  • response (Response 对象) – 发生异常时正在处理的响应

  • exception (Exception 对象) – 引发的异常

  • spider (Spider 对象) – 引发异常的蜘蛛

process_start_requests(start_requests, spider)

此方法使用蜘蛛的起始请求调用,其工作方式类似于process_spider_output() 方法,不同之处在于它没有关联的响应,并且只能返回请求(而不是项目)。

它接收一个可迭代对象(在 start_requests 参数中),并且必须返回另一个 Request 对象和/或item 对象 的可迭代对象。

注意

在蜘蛛中间件中实现此方法时,应始终返回一个可迭代对象(遵循输入对象),并且不要消耗所有 start_requests 迭代器,因为它可能非常大(甚至无限),并导致内存溢出。Scrapy 引擎设计为在有能力处理请求时提取起始请求,因此起始请求迭代器可以有效地无限循环,而存在其他停止蜘蛛的条件(例如时间限制或项目/页面计数)。

参数:
  • start_requests (Request 的可迭代对象) – 起始请求

  • spider (Spider 对象) – 起始请求所属的蜘蛛

from_crawler(cls, crawler)

如果存在,则会调用此类方法以从Crawler 创建中间件实例。它必须返回中间件的新实例。Crawler 对象提供对所有 Scrapy 核心组件(如设置和信号)的访问;它是中间件访问它们并将功能挂钩到 Scrapy 的一种方式。

参数:

crawler (Crawler 对象) – 使用此中间件的爬虫

内置蜘蛛中间件参考

此页面描述了 Scrapy 附带的所有蜘蛛中间件组件。有关如何使用它们以及如何编写自己的蜘蛛中间件的信息,请参阅蜘蛛中间件使用指南

有关默认启用的组件(及其顺序)的列表,请参阅SPIDER_MIDDLEWARES_BASE 设置。

DepthMiddleware

class scrapy.spidermiddlewares.depth.DepthMiddleware[source]

DepthMiddleware 用于跟踪正在抓取的站点内每个 Request 的深度。它的工作原理是,在之前没有设置值(通常只是第一个 Request)时设置 request.meta['depth'] = 0,否则将其递增 1。

它可以用来限制要抓取的最大深度,根据深度控制 Request 优先级,以及类似的事情。

DepthMiddleware 可以通过以下设置进行配置(有关更多信息,请参阅设置文档)

  • DEPTH_LIMIT - 允许对任何站点抓取的最大深度。如果为零,则不会施加限制。

  • DEPTH_STATS_VERBOSE - 是否收集每个深度的请求数量。

  • DEPTH_PRIORITY - 是否根据深度对请求进行优先级排序。

HttpErrorMiddleware

class scrapy.spidermiddlewares.httperror.HttpErrorMiddleware[source]

过滤掉不成功的(错误的)HTTP 响应,以便蜘蛛不必处理它们,这(大多数情况下)会带来开销,消耗更多资源,并使蜘蛛逻辑更加复杂。

根据HTTP 标准,成功的响应是状态代码在 200-300 范围内的响应。

如果您仍然希望处理该范围之外的响应代码,则可以使用 handle_httpstatus_list 蜘蛛属性或HTTPERROR_ALLOWED_CODES 设置指定蜘蛛能够处理哪些响应代码。

例如,如果您希望您的蜘蛛处理 404 响应,您可以这样做

from scrapy.spiders import CrawlSpider


class MySpider(CrawlSpider):
    handle_httpstatus_list = [404]

Request.metahandle_httpstatus_list 密钥也可以用来指定每个请求允许哪些响应代码。如果要允许请求的任何响应代码,可以将元数据键 handle_httpstatus_all 设置为 True,如果要禁用 handle_httpstatus_all 密钥的效果,则将其设置为 False

但是,请记住,处理非 200 响应通常不是一个好主意,除非您确实知道自己在做什么。

有关更多信息,请参阅:HTTP 状态代码定义

HttpErrorMiddleware 设置

HTTPERROR_ALLOWED_CODES

默认值:[]

传递包含在此列表中的所有非 200 状态代码的响应。

HTTPERROR_ALLOW_ALL

默认值:False

传递所有响应,无论其状态代码如何。

RefererMiddleware

class scrapy.spidermiddlewares.referer.RefererMiddleware[source]

根据生成它的响应的 URL,填充请求的 Referer 标头。

RefererMiddleware 设置

REFERER_ENABLED

默认值:True

是否启用 Referer 中间件。

REFERRER_POLICY

默认值:'scrapy.spidermiddlewares.referer.DefaultReferrerPolicy'

填充请求“Referer”标头时要应用的Referrer 策略

注意

您还可以使用特殊的 "referrer_policy" Request.meta 键(与 REFERRER_POLICY 设置接受的相同值)为每个请求设置 Referrer 策略。

REFERRER_POLICY 接受的值
  • 可以是 scrapy.spidermiddlewares.referer.ReferrerPolicy 子类的路径(自定义策略或内置策略之一,请参见下面的类),

  • 或者是一个或多个逗号分隔的标准 W3C 定义的字符串值,

  • 或者特殊的 "scrapy-default"

字符串值

类名(作为字符串)

"scrapy-default"(默认)

scrapy.spidermiddlewares.referer.DefaultReferrerPolicy

“no-referrer”

scrapy.spidermiddlewares.referer.NoReferrerPolicy

“no-referrer-when-downgrade”

scrapy.spidermiddlewares.referer.NoReferrerWhenDowngradePolicy

“same-origin”

scrapy.spidermiddlewares.referer.SameOriginPolicy

“origin”

scrapy.spidermiddlewares.referer.OriginPolicy

“strict-origin”

scrapy.spidermiddlewares.referer.StrictOriginPolicy

“origin-when-cross-origin”

scrapy.spidermiddlewares.referer.OriginWhenCrossOriginPolicy

“strict-origin-when-cross-origin”

scrapy.spidermiddlewares.referer.StrictOriginWhenCrossOriginPolicy

“unsafe-url”

scrapy.spidermiddlewares.referer.UnsafeUrlPolicy

class scrapy.spidermiddlewares.referer.DefaultReferrerPolicy[source]

“no-referrer-when-downgrade” 的变体,另外如果父请求使用 file://s3:// 方案,则不会发送“Referer”。

警告

Scrapy 的默认 Referrer 策略(就像 “no-referrer-when-downgrade”,浏览器推荐的 W3C 值一样)会从任何 http(s):// 发送非空的“Referer”标头到任何 https:// URL,即使域不同。

如果您想删除跨域请求的 Referrer 信息,“same-origin” 可能是更好的选择。

class scrapy.spidermiddlewares.referer.NoReferrerPolicy[source]

https://www.w3.org/TR/referrer-policy/#referrer-policy-no-referrer

最简单的策略是“no-referrer”,它指定不将任何 Referrer 信息与从特定请求客户端到任何来源的请求一起发送。标头将完全省略。

class scrapy.spidermiddlewares.referer.NoReferrerWhenDowngradePolicy[source]

https://www.w3.org/TR/referrer-policy/#referrer-policy-no-referrer-when-downgrade

“no-referrer-when-downgrade” 策略会将完整的 URL 与来自 TLS 保护的环境设置对象的请求发送到可能值得信赖的 URL,以及来自未经 TLS 保护的客户端的请求发送到任何来源。

另一方面,来自 TLS 保护客户端到非可能值得信赖的 URL 的请求将不包含任何 Referrer 信息。不会发送 Referer HTTP 标头。

如果未另行指定策略,这是用户代理的默认行为。

注意

“no-referrer-when-downgrade” 策略是 W3C 推荐的默认策略,并且被主要的网络浏览器使用。

但是,它不是 Scrapy 的默认 Referrer 策略(请参见 DefaultReferrerPolicy)。

class scrapy.spidermiddlewares.referer.SameOriginPolicy[source]

https://www.w3.org/TR/referrer-policy/#referrer-policy-same-origin

“same-origin” 策略指定当从特定请求客户端发出同源请求时,将完整 URL(已剥离以用作 Referrer)作为 Referrer 信息发送。

另一方面,跨源请求将不包含任何 Referrer 信息。不会发送 Referer HTTP 标头。

class scrapy.spidermiddlewares.referer.OriginPolicy[source]

https://www.w3.org/TR/referrer-policy/#referrer-policy-origin

“origin” 策略指定仅将请求客户端来源的 ASCII 序列化作为 Referrer 信息发送,无论从特定请求客户端发出同源请求还是跨源请求。

class scrapy.spidermiddlewares.referer.StrictOriginPolicy[source]

https://www.w3.org/TR/referrer-policy/#referrer-policy-strict-origin

“strict-origin” 策略在发出请求时发送请求客户端来源的 ASCII 序列化:- 从 TLS 保护的环境设置对象到可能值得信赖的 URL,以及 - 从非 TLS 保护的环境设置对象到任何来源。

另一方面,来自 TLS 保护请求客户端到非可能值得信赖的 URL 的请求将不包含任何 Referrer 信息。不会发送 Referer HTTP 标头。

class scrapy.spidermiddlewares.referer.OriginWhenCrossOriginPolicy[source]

https://www.w3.org/TR/referrer-policy/#referrer-policy-origin-when-cross-origin

“origin-when-cross-origin” 策略指定当从特定请求客户端发出同源请求时,将完整 URL(已剥离以用作 Referrer)作为 Referrer 信息发送,并且仅在从特定请求客户端发出跨源请求时,将请求客户端来源的 ASCII 序列化作为 Referrer 信息发送。

class scrapy.spidermiddlewares.referer.StrictOriginWhenCrossOriginPolicy[source]

https://www.w3.org/TR/referrer-policy/#referrer-policy-strict-origin-when-cross-origin

“strict-origin-when-cross-origin” 策略指定当从特定请求客户端发出同源请求时,将完整 URL(已剥离以用作 Referrer)作为 Referrer 信息发送,并且仅在发出跨源请求时发送请求客户端来源的 ASCII 序列化

  • 从 TLS 保护的环境设置对象到可能值得信赖的 URL,以及

  • 从非 TLS 保护的环境设置对象到任何来源。

另一方面,来自 TLS 保护客户端到非可能值得信赖的 URL 的请求将不包含任何 Referrer 信息。不会发送 Referer HTTP 标头。

class scrapy.spidermiddlewares.referer.UnsafeUrlPolicy[source]

https://www.w3.org/TR/referrer-policy/#referrer-policy-unsafe-url

“unsafe-url” 策略指定将完整 URL(已剥离以用作 Referrer)与从特定请求客户端发出的跨源请求和同源请求一起发送。

注意:策略的名称没有说谎;它是不安全的。此策略会将来自 TLS 保护资源的来源和路径泄漏到不安全的来源。仔细考虑为可能敏感的文档设置此类策略的影响。

警告

不建议使用“unsafe-url”策略。

UrlLengthMiddleware

class scrapy.spidermiddlewares.urllength.UrlLengthMiddleware[source]

过滤掉 URL 长度超过 URLLENGTH_LIMIT 的请求。

可以通过以下设置配置 UrlLengthMiddleware(有关更多信息,请参阅设置文档)