Scrapy Downloader Middleware 执行机制完全总结
本笔记彻底讲清三个问题: 一、Downloader Middleware 正常执行流程 二、process_request 返回 Response 会发生什么? 本质理解 三、process_request 返回 Request 会发生什么? 重要 如果无条件 return request 会导致: 四、process_request 返回 None 会发生什么? 五、三种返回值对比总结 六、完整模型理解 A ← B ← C 七、一句话总总结
假设中间件顺序:
MiddlewareA
MiddlewareB
MiddlewareC
正常流程(没有中断)
Engine
↓
A.process_request
↓
B.process_request
↓
C.process_request
↓
Downloader
↓
C.process_response
↓
B.process_response
↓
A.process_response
↓
Engine
↓
Spider
特点:
● process_request 正向执行
● process_response 反向执行
示例:
def process_request(self, request, spider):return HtmlResponse(url=request.url, body=b"mock", encoding="utf-8")
Engine
↓
A.process_request
↓
B.process_request ← 返回 Response
↓
(停止执行 C.process_request)
(跳过 Downloader)
↓
C.process_response
↓
B.process_response
↓
A.process_response
↓
Engine
↓
Spider
关键结论
● 不会进入下载器
● 不会执行后续 process_request
● 会进入 process_response 链
● 会按反向顺序执行
● 最终交给 Spider
返回 Response = 中断 request 链,直接开始 response 链
示例:
def process_request(self, request, spider):request.meta["flag"] = True
return request
A.process_request ← 返回 Request
↓
停止当前 middleware 链
↓
重新进入 Scheduler
↓
重新走 Engine
↓
重新进入 process_request 链
关键结论
● 不会进入下载器
● 不会继续执行后续 process_request
● 不会进入 process_response
● 会被重新调度
return request ≠ 发包
return request = 重新调度
def process_request(self, request, spider):return request
无限循环
必须加条件控制:
def process_request(self, request, spider):if not request.meta.get("retry_flag"):
request.meta["retry_flag"] = True
return request
示例:
def process_request(self, request, spider):request.headers["User-Agent"] = "xxx"
return None
继续执行下一个 middleware 的 process_request
最终进入 Downloader
返回值 是否继续 process_request 是否进入 Downloader 是否进入 process_response 是否重新调度
None ✅ 是 ✅ 是 ✅ 是 ❌ 否
Response ❌ 否 ❌ 否 ✅ 是 ❌ 否
Request ❌ 否 ❌ 否 ❌ 否 ✅ 是
可以把 Downloader Middleware 理解为:
正向
A → B → C → Downloader 反向
情况一:return None
继续正向 → 到 Downloader → 再反向
情况二:return Response
停止正向 → 直接开始反向
情况三:return Request
停止正向 → 重新调度 → 从头开始
● return None → 正常流转
● return Response → 跳过下载器,进入 response 链
● return Request → 重新调度
● return request 不是发包,而是回炉重造