5月31日 01:07

Scrapy 数据流从请求到入库是如何运转的?

Scrapy 的数据流可以理解成一条异步流水线:Spider 产生请求,Engine 负责协调,Scheduler 排队和去重,Downloader 取回响应,Spider 再解析响应并产出新的请求或 Item,最后 Item 进入 Pipeline。真正的核心不是某一个组件,而是 Engine 在这些组件之间来回转发数据。

启动爬虫后,Engine 会向 Spider 索要初始请求,并交给 Scheduler。Scheduler 保存请求,Downloader Middleware 可以在下载前改请求头、代理或 cookie,Downloader 拿到响应后再经过 Middleware 返回给 Spider。Spider 的回调函数解析页面,如果产出 Request,就回到 Scheduler;如果产出 Item,就交给 Pipeline。这个循环持续到队列清空、运行被停止或触发关闭条件。

text
Spider -> Engine -> Scheduler -> Engine -> Downloader Downloader -> Engine -> Spider -> Item Pipeline Spider -> new Request -> Scheduler

常见配置会影响这条数据流的节奏:

python
CONCURRENT_REQUESTS = 16 DOWNLOAD_DELAY = 0.5 RETRY_ENABLED = True RETRY_TIMES = 2 DOWNLOADER_MIDDLEWARES = { 'myproject.middlewares.ProxyMiddleware': 350, } ITEM_PIPELINES = { 'myproject.pipelines.StorePipeline': 300, }

追问

Engine 在 Scrapy 数据流里到底做什么?

Engine 是调度中枢,它不负责解析页面,也不负责真正下载,而是决定请求和响应该交给谁。它向 Scheduler 要请求,把请求交给 Downloader,再把响应交给 Spider。取舍是这种拆分让组件边界清楚,也让中间件和扩展有插入点。边界是业务代码通常不直接操作 Engine,调试时更多看日志、信号和各组件输入输出。

Scheduler 和 Downloader 的关系是什么?

Scheduler 只管请求排队、优先级和去重,Downloader 只管把某个请求变成响应。Engine 从 Scheduler 取出下一个请求,再交给 Downloader 执行下载。踩坑点是把“为什么这个 URL 没抓”都归因于 Downloader,其实它可能早就在 Scheduler 阶段被去重过滤了。排查时应先看 dupefilter 日志,再看下载状态码和异常。

Middleware 在数据流中适合做哪些事?

Downloader Middleware 适合处理请求发送前和响应返回后的横切逻辑,比如代理、User-Agent、重试、异常响应处理。Spider Middleware 更靠近解析层,适合处理进入或离开 spider 的 response、request、item。取舍是 Middleware 很强,但滥用会让数据流变得不透明。边界建议是:和网络请求相关的放 Downloader Middleware,和解析结果相关的放 Spider Middleware,不要把入库逻辑塞进去。

Scrapy 为什么能同时处理很多请求?

Scrapy 基于 Twisted 的异步事件模型,等待网络响应时不会阻塞整个进程,可以继续处理其他请求。它适合 I/O 密集型爬取,尤其是大量网页下载场景。边界是解析函数里如果写了 CPU 很重的代码,或者调用同步阻塞接口,异步优势会被抵消。踩坑最多的是在回调里直接做大文件处理、慢 SQL 或 time.sleep(),结果并发配置再高也跑不起来。

数据流排查应该从哪里开始?

先看请求有没有进入 Scheduler,再看是否被去重,然后看 Downloader 返回的状态码,最后看 Spider 是否产出 Item 或新 Request。这个顺序比直接盯着 pipeline 更有效,因为很多问题根本没走到入库阶段。取舍是全链路日志会增加噪音,但在调试复杂爬虫时非常值。生产环境可以只保留关键统计,例如请求数、去重数、非 200 响应数、item 数和 drop 数。

标签:Scrapy