爬虫中间件
爬虫中间件是 Scrapy 爬虫处理机制中的钩子框架,你可以在其中插入自定义功能来处理发送给 Spiders 进行处理的响应,以及处理由爬虫生成的请求和项目。
激活爬虫中间件
要激活一个爬虫中间件组件,请将其添加到 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, spider)
此方法为通过爬虫中间件并进入爬虫进行处理的每个响应调用。
process_spider_input() 应该返回 None 或引发异常。
- 如果它返回
None,Scrapy 将继续处理此响应,执行所有其他中间件,直到最终将响应交给爬虫进行处理。 - 如果它引发异常,Scrapy 将不会调用任何其他爬虫中间件的
process_spider_input(),如果存在请求 errback,则将调用它,否则将启动process_spider_exception()链。errback 的输出将沿另一个方向链接回process_spider_output()进行处理,如果它引发异常,则由process_spider_exception()处理。
参数:
- response (
Response对象) – 正在处理的响应 - spider (
Spider对象) – 此响应所属的爬虫
process_spider_output(response, result, spider)
此方法在 Spider 处理响应后,使用 Spider 返回的结果调用。
process_spider_output() 必须返回 Request 对象和 item 对象的迭代器。
版本 2.7 中的变化: 此方法可以定义为异步生成器,在这种情况下 result 是一个异步迭代器。
考虑将此方法定义为异步生成器,这将是 Scrapy 未来版本中的要求。但是,如果你打算与其他人共享你的爬虫中间件,请考虑强制将 Scrapy 2.7 作为你的爬虫中间件的最低要求,或者使你的爬虫中间件通用,以便它与 Scrapy 2.7 之前的版本一起工作。
参数:
- response (
Response对象) – 爬虫生成此输出的响应 - result (
Request对象和item对象的迭代器) – 爬虫返回的结果 - spider (
Spider对象) – 正在处理其结果的爬虫
async 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 或 Request 或 item 对象的迭代器。
- 如果它返回
None,Scrapy 将继续处理此异常,执行后续中间件组件中的任何其他process_spider_exception(),直到没有中间件组件留下并且异常到达引擎(在那里它被记录和丢弃)。 - 如果它返回一个可迭代对象,
process_spider_output()管道将启动,从下一个爬虫中间件开始,并且不会调用其他process_spider_exception()。
参数:
- response (
Response对象) – 异常引发时正在处理的响应 - exception (
Exception对象) – 引发的异常 - spider (
Spider对象) – 引发异常的爬虫
自定义爬虫中间件的基类
Scrapy 为自定义爬虫中间件提供了一个基类。不需要使用它,但它可以帮助简化中间件实现并减少通用中间件中的样板代码量。
class scrapy.spidermiddlewares.base.BaseSpiderMiddleware(crawler: Crawler)[source]
可选的爬虫中间件基类。
版本 2.13 新增。
此类为异步 process_spider_output() 和 process_start() 方法提供帮助方法。没有这些方法的中间件不需要使用此类。
你可以覆盖 get_processed_request() 方法以添加请求的处理代码,并覆盖 get_processed_item() 方法以添加项目的处理代码。这些方法从爬虫输出迭代器中获取单个请求或项目,并返回一个请求或项目(相同或新的),或者返回 None 以从处理中删除此请求或项目。
get_processed_item(item: Any, response: Response | None) -> Any[source]
从爬虫输出返回已处理的项目。
此方法从启动种子或爬虫输出中获取单个项目。它应该返回相同或不同的项目,或者返回 None 以忽略它。
参数:
- item (项目对象) – 输入项目
- response (
Response对象或None用于启动种子) – 正在处理的响应
返回:
已处理的项目或 None
get_processed_request(request: Request, response: Response | None) -> Request | None[source]
从爬虫输出返回已处理的请求。
此方法从启动种子或爬虫输出中获取单个请求。它应该返回相同或不同的请求,或者返回 None 以忽略它。
参数:
- request (
Request对象) – 输入请求 - response (
Response对象或None用于启动种子) – 正在处理的响应
返回:
已处理的请求或 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.HttpErrorMiddlewaresource
过滤掉不成功的(错误的)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
class scrapy.spidermiddlewares.referer.RefererMiddlewaresource
根据生成它的 Response 的 URL 填充 Request 的 Referer 头。
RefererMiddleware 设置
REFERER_ENABLED- 默认值:
True - 是否启用 referer 中间件。
- 默认值:
REFERRER_POLICY- 默认值:
'scrapy.spidermiddlewares.referer.DefaultReferrerPolicy' - 填充
Request“Referer” 头时要应用的 Referrer Policy。
- 默认值:
注意: 你也可以使用特殊的 "referrer_policy" Request.meta 键按请求设置 Referrer Policy,其可接受值与 REFERRER_POLICY 设置相同。
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 policy——就像 “no-referrer-when-downgrade”,W3C 推荐的浏览器值一样——将从任何 http(s):// 向任何 https:// URL 发送一个非空的 “Referer” 头,即使域名不同。如果你希望删除跨域请求的 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 policy(请参阅 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 信息;当从受 TLS 保护的环境设置对象到可能可信的 URL,以及从非 TLS 保护的环境设置对象到任何来源的跨源请求时,仅发送请求客户端起源的 ASCII 序列化。
另一方面,从受 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” 策略。
StartSpiderMiddleware
class scrapy.spidermiddlewares.start.StartSpiderMiddleware(crawler: Crawler)[source]
设置 is_start_request。
is_start_request- 在启动请求中设置为
True的meta键,允许你区分启动请求和其他请求,例如在下载器中间件中。
- 在启动请求中设置为
UrlLengthMiddleware
class scrapy.spidermiddlewares.urllength.UrlLengthMiddleware[source]
过滤掉 URL 长度超过 URLLENGTH_LIMIT 的请求。
UrlLengthMiddleware 可以通过以下设置进行配置(有关更多信息,请参阅设置文档):
URLLENGTH_LIMIT- 允许抓取 URL 的最大 URL 长度。