爬虫中间件
爬虫中间件是 Scrapy 爬虫处理机制中的一个钩子框架,您可以在其中插入自定义功能来处理发送给爬虫进行处理的响应,以及处理从爬虫生成的请求和数据项。
激活爬虫中间件
要激活一个爬虫中间件组件,请将其添加到 SPIDER_MIDDLEWARES 设置中,该设置是一个字典,其键是中间件的类路径,值是中间件的顺序。
这里是一个例子
SPIDER_MIDDLEWARES = {
"myproject.middlewares.CustomSpiderMiddleware": 543,
}
将 SPIDER_MIDDLEWARES 设置与 Scrapy 中定义的 SPIDER_MIDDLEWARES_BASE 设置(不应被覆盖)合并,然后按顺序排序,得到最终启用的中间件列表:第一个中间件离引擎最近,最后一个离爬虫最近。换句话说,每个中间件的 process_spider_input() 方法将按中间件顺序递增(100、200、300…)调用,而每个中间件的 process_spider_output() 方法将按递减顺序调用。
要决定给您的中间件分配哪个顺序,请参阅 SPIDER_MIDDLEWARES_BASE 设置,并根据您想要插入中间件的位置选择一个值。顺序很重要,因为每个中间件执行不同的操作,并且您的中间件可能依赖于某个先前(或后续)中间件的应用。
如果您想禁用一个内置中间件(在 SPIDER_MIDDLEWARES_BASE 中定义并默认启用的那些),您必须在项目的 SPIDER_MIDDLEWARES 设置中定义它,并将其值设为 None。例如,如果您想禁用站外中间件
SPIDER_MIDDLEWARES = {
"scrapy.spidermiddlewares.referer.RefererMiddleware": None,
"myproject.middlewares.CustomRefererSpiderMiddleware": 700,
}
最后,请记住,某些中间件可能需要通过特定设置启用。请参阅每个中间件的文档以获取更多信息。
编写自己的爬虫中间件
每个爬虫中间件都是一个组件,它定义了一个或多个以下方法
- class scrapy.spidermiddlewares.SpiderMiddleware
- async process_start(start: AsyncIterator[Any], /) AsyncIterator[Any]
迭代
start()的输出,或早期爬虫中间件的process_start()方法的输出,并覆盖它。例如async def process_start(self, start): async for item_or_request in start: yield item_or_request
您可以生成与
start()相同类型的对象。要编写适用于 Scrapy 2.13 以下版本的爬虫中间件,还需要定义一个返回可迭代对象的同步
process_start_requests()方法。例如def process_start_requests(self, start, spider): yield from start
- process_spider_input(response)
此方法针对每个经过爬虫中间件并进入爬虫进行处理的响应调用。
process_spider_input()应该返回None或抛出异常。如果它返回
None,Scrapy 将继续处理此响应,执行所有其他中间件,直到最终将响应交给爬虫进行处理。如果它抛出异常,Scrapy 将不再调用任何其他爬虫中间件的
process_spider_input()方法,并且如果存在请求错误回调,则会调用它,否则将启动process_spider_exception()链。错误回调的输出将反向链接回process_spider_output()进行处理,如果它也抛出异常,则链接回process_spider_exception()。- 参数:
response (
Response对象) – 正在处理的响应
- async process_spider_output_async(response, result)
实现通用爬虫中间件时,
process_spider_output()的替代名称。
- process_spider_exception(response, exception)
当爬虫或
process_spider_output()方法(来自前一个爬虫中间件)抛出异常时,会调用此方法。process_spider_exception()应该返回None或一个包含Request或数据项对象的迭代器。如果它返回
None,Scrapy 将继续处理此异常,执行后续中间件组件中的任何其他process_spider_exception(),直到没有中间件组件剩下,异常到达引擎(在那里它被记录并丢弃)。如果它返回一个迭代器,则
process_spider_output()管道将从下一个爬虫中间件开始启动,并且不会调用其他process_spider_exception()。
通用爬虫中间件
在 Scrapy 2.6.3 及更低版本中,process_spider_output() 必须是一个同步生成器。
为了在同一个中间件中支持这些版本和更高的 Scrapy 版本,请将您的异步 process_spider_output() 方法重命名为 process_spider_output_async(),并定义一个供 2.6.3 及更低版本使用的同步 process_spider_output() 方法。
例如
class UniversalSpiderMiddleware:
async def process_spider_output_async(self, response, result):
async for r in result:
# ... do something with r
yield r
def process_spider_output(self, response, result):
for r in result:
# ... do something with r
yield r
自定义爬虫中间件的基类
Scrapy 提供了一个自定义爬虫中间件的基类。虽然不是强制要求使用,但它可以帮助简化中间件的实现。
- class scrapy.spidermiddlewares.base.BaseSpiderMiddleware(crawler: Crawler)[source]
爬虫中间件的可选基类。
2.13 版本中新增。
这个类为异步
process_spider_output()和process_start()方法提供了辅助方法。不具备这些方法的中间件不需要使用这个类。您可以覆盖
get_processed_request()方法来添加请求的处理代码,并覆盖get_processed_item()方法来添加数据项的处理代码。这些方法从爬虫输出的可迭代对象中获取单个请求或数据项,并返回一个请求或数据项(相同或新的),或者返回None以将其从处理中移除。
内置爬虫中间件参考
本页描述了 Scrapy 附带的所有爬虫中间件组件。有关如何使用它们以及如何编写自己的爬虫中间件的信息,请参阅爬虫中间件使用指南。
有关默认启用组件(及其顺序)的列表,请参阅 SPIDER_MIDDLEWARES_BASE 设置。
DepthMiddleware
- class scrapy.spidermiddlewares.depth.DepthMiddleware[source]
DepthMiddleware 用于跟踪正在抓取网站中每个 Request 的深度。它的工作原理是:当
request.meta['depth']没有预设值时(通常是第一个 Request),将其设置为0,否则将其递增 1。它可用于限制最大抓取深度,根据请求深度控制请求优先级等。
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.meta 的 handle_httpstatus_list 键也可以用于按请求指定允许哪些响应代码。如果您希望允许请求的任何响应代码,您还可以将 meta 键 handle_httpstatus_all 设置为 True,设置为 False 则禁用 handle_httpstatus_all 键的效果。
然而,请记住,处理非 200 响应通常不是一个好主意,除非您非常清楚自己在做什么。
有关更多信息,请参阅:HTTP 状态码定义。
HttpErrorMiddleware 设置
HTTPERROR_ALLOWED_CODES
默认值:[]
通过此列表中包含的非 200 状态码的所有响应。
HTTPERROR_ALLOW_ALL
默认值:False
通过所有响应,无论其状态码如何。
RefererMiddleware
RefererMiddleware 设置
REFERER_ENABLED
默认值:True
是否启用 referer 中间件。
REFERRER_POLICY
默认值:'scrapy.spidermiddlewares.referer.DefaultReferrerPolicy'
填充请求 “Referer” 头时应用的Referer 策略。
注意
您还可以通过使用特殊的 "referrer_policy" Request.meta 键,为每个请求设置 Referer 策略,其可接受值与 REFERRER_POLICY 设置相同。
另请参阅
REFERRER_POLICY 的可接受值
要么是
scrapy.spidermiddlewares.referer.ReferrerPolicy子类的路径——一个自定义策略或内置策略之一(见下面的类),或一个或多个逗号分隔的标准 W3C 定义的字符串值,
或特殊的
"scrapy-default"。
- class scrapy.spidermiddlewares.referer.DefaultReferrerPolicy[source]
“no-referrer-when-downgrade” 的一个变体,额外增加了如果父请求使用
file://或s3://方案,则不发送 “Referer” 头。
警告
Scrapy 的默认 Referer 策略——就像 “no-referrer-when-downgrade”(W3C 为浏览器推荐的值)一样——将从任何 http(s):// URL 向任何 https:// URL 发送一个非空的 “Referer” 头,即使域名不同。
如果您希望为跨域请求移除 referrer 信息,“same-origin” 可能是一个更好的选择。
- class scrapy.spidermiddlewares.referer.NoReferrerPolicy[source]
https://w3org.cn/TR/referrer-policy/#referrer-policy-no-referrer
最简单的策略是“no-referrer”,它指定从特定请求客户端向任何源发出的请求不发送任何 referrer 信息。此头将被完全省略。
- class scrapy.spidermiddlewares.referer.NoReferrerWhenDowngradePolicy[source]
https://w3org.cn/TR/referrer-policy/#referrer-policy-no-referrer-when-downgrade
“no-referrer-when-downgrade” 策略会在从受 TLS 保护的环境设置对象向潜在可信 URL 发出的请求中,以及从不受 TLS 保护的客户端向任何源发出的请求中,发送完整的 URL。
另一方面,从受 TLS 保护的客户端向非潜在可信 URL 发出的请求将不包含任何 referrer 信息。不会发送 Referer HTTP 头。
如果未另外指定策略,这是用户代理的默认行为。
注意
“no-referrer-when-downgrade” 策略是 W3C 推荐的默认值,并被主要网络浏览器使用。
然而,它不是 Scrapy 的默认 Referer 策略(请参阅 DefaultReferrerPolicy)。
- class scrapy.spidermiddlewares.referer.SameOriginPolicy[source]
https://w3org.cn/TR/referrer-policy/#referrer-policy-same-origin
“same-origin” 策略指定,当从特定请求客户端发出同源请求时,将发送一个作为 referrer 使用的完整 URL(已剥离)。
另一方面,跨源请求将不包含任何 referrer 信息。不会发送 Referer HTTP 头。
- class scrapy.spidermiddlewares.referer.OriginPolicy[source]
https://w3org.cn/TR/referrer-policy/#referrer-policy-origin
“origin” 策略指定,当从特定请求客户端发出同源请求和跨源请求时,仅发送请求客户端源的 ASCII 序列化作为 referrer 信息。
- class scrapy.spidermiddlewares.referer.StrictOriginPolicy[source]
https://w3org.cn/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://w3org.cn/TR/referrer-policy/#referrer-policy-origin-when-cross-origin
“origin-when-cross-origin” 策略指定,当从特定请求客户端发出同源请求时,将发送一个作为 referrer 使用的完整 URL(已剥离),而当从特定请求客户端发出跨源请求时,仅发送请求客户端源的 ASCII 序列化作为 referrer 信息。
- class scrapy.spidermiddlewares.referer.StrictOriginWhenCrossOriginPolicy[source]
https://w3org.cn/TR/referrer-policy/#referrer-policy-strict-origin-when-cross-origin
“strict-origin-when-cross-origin” 策略指定,当从特定请求客户端发出同源请求时,将发送一个作为 referrer 使用的完整 URL(已剥离),而当发出跨源请求时,仅发送请求客户端源的 ASCII 序列化,具体如下:
从受 TLS 保护的环境设置对象向潜在可信 URL 发出时,以及
从非 TLS 保护的环境设置对象向任何源发出时。
另一方面,从受 TLS 保护的客户端向非潜在可信 URL 发出的请求将不包含任何 referrer 信息。不会发送 Referer HTTP 头。
- class scrapy.spidermiddlewares.referer.UnsafeUrlPolicy[source]
https://w3org.cn/TR/referrer-policy/#referrer-policy-unsafe-url
“unsafe-url” 策略指定,当从特定请求客户端发出跨源请求和同源请求时,都会发送一个作为 referrer 使用的完整 URL(已剥离)。
注意:此策略的名称并非虚言;它不安全。此策略会将 TLS 保护资源的源和路径泄露给不安全的源。请仔细考虑为潜在敏感文档设置此类策略的影响。
警告
不推荐使用“unsafe-url”策略。
REFERRER_POLICIES
版本 2.14.2 中新增。
默认值:{}
一个字典,将策略名称映射到 scrapy.spidermiddlewares.referer.ReferrerPolicy 子类的导入路径,或者 None 以禁用对给定策略名称的支持。
这允许覆盖由 Referrer-Policy 响应头触发的策略。
使用 "" 来覆盖没有 referrer 策略的响应的策略。
StartSpiderMiddleware
UrlLengthMiddleware
- class scrapy.spidermiddlewares.urllength.UrlLengthMiddleware[source]
过滤掉 URL 长度超过 URLLENGTH_LIMIT 的请求
UrlLengthMiddleware可以通过以下设置进行配置(有关更多信息,请参阅设置文档)URLLENGTH_LIMIT- 允许抓取 URL 的最大 URL 长度。