柳嘉希

硕士研究生毕业生

软件工程师 | 可扩展的API · 网络爬虫 · 数据集成 · Vibe代码清理专家

Scrapy 复习:Engine、Scheduler、Downloader、Spider、Pipeline 与 Selector

Scrapy 不是一个简单的 HTML 解析库,而是完整的爬虫框架。它负责请求调度、下载、解析、数据管道和中间件扩展。

核心组件

Scrapy Engine 负责协调各组件。

Scheduler 接收 Request,排序入队,并在引擎需要时交还请求。

Downloader 负责发送请求并返回 Response。

Spider 负责解析 Response,提取 Item 和新的 URL。

Item Pipeline 负责清洗、过滤、保存数据。

Middleware 可以拦截请求和响应,适合加代理、User-Agent、Cookie 或接入浏览器渲染。

运行流程

  1. Spider 给出初始 URL。
  2. Engine 把 Request 交给 Scheduler。
  3. Scheduler 排队。
  4. Engine 从 Scheduler 取 Request。
  5. Downloader 下载页面。
  6. Response 交给 Spider。
  7. Spider 提取 Item 和新 Request。
  8. Item 进入 Pipeline,新 Request 回到 Scheduler。
  9. 队列为空时爬虫结束。

Selector

Scrapy 使用 Selector 解析 HTML/XML。

def parse(self, response):
    title = response.xpath("//title/text()").get()

XPath 常用写法:

//tag
//div[@class="content"]
//a/@href
//h1/text()
//ul/li[position()=1]

CSS 选择器:

title = response.css("title::text").get()
links = response.css("a::attr(href)").getall()

get 与 getall

.get() 获取第一个匹配结果。

title = response.xpath("//title/text()").get()

.getall() 获取全部结果。

tags = response.css("a.tag::text").getall()

分页

def parse(self, response):
    for quote in response.css("div.quote"):
        yield {
            "text": quote.css("span.text::text").get(),
            "author": quote.css("small.author::text").get(),
        }
 
    next_page = response.css("li.next a::attr(href)").get()
    if next_page:
        yield response.follow(next_page, self.parse)

工具选择

优先级一般是:

  1. 静态 HTML:Scrapy XPath/CSS
  2. 页面内 JSON:直接解析 JSON
  3. 轻微 JS:scrapy-playwright
  4. 强交互页面:Selenium
  5. HTML 结构很脏:BeautifulSoup 辅助清洗

Scrapy 的价值在于框架化、可扩展和适合大规模抓取。

延伸理解

复习这篇时,不要只记住名词,要把重点放在 Scrapy Engine、Scheduler、Downloader、Spider、Item Pipeline、Selector 和分页。这类知识如果只停留在定义层面,很容易在面试或项目中答得很散。更好的理解方式是把它放进一个具体场景:谁在调用它,输入从哪里来,失败后谁负责恢复,数据或状态会不会被重复处理。

  • 爬虫工程的难点通常不是发请求,而是页面变化、等待策略、去重、限速、异常恢复和数据质量。
  • 选择 BeautifulSoup、Selenium 或 Scrapy 时,要先判断页面是否动态、数据规模和后续清洗需求。
  • 可靠爬虫需要日志、断点续跑、失败重试和字段级校验,不能只依赖一次成功运行。

在真实项目中,可以把它当成一个判断框架:先确认输入、约束、失败场景和可观测性,再决定具体工具或写法。 如果一个方案看起来很简单,要继续追问它在规模扩大、权限变化、异常恢复和团队协作下是否仍然成立。

实践检查清单

  • 明确这个知识点在系统中的位置:是开发时约束、运行时能力、基础设施能力,还是协作流程。
  • 写出一个最小可运行例子,并补一个失败例子;只会写 happy path 说明理解还不够稳。
  • 记录常见误用:例如边界条件、权限假设、性能假设、同步/异步差异或环境差异。
  • 把概念和项目经历关联起来:如果面试被追问,可以用自己的项目说明为什么这样选。
  • 最后用一句话总结取舍:它牺牲了什么,换来了什么。

自测问题

  1. 这个主题解决的核心问题是什么?
  2. 如果不用当前方案,还有哪些替代方案?代价是什么?
  3. 最容易出错的边界条件在哪里?
  4. 如何在代码、测试或监控中验证它真的可靠?

项目化应用场景

可以把这类知识放到一个招聘信息或商品信息采集系统里理解:先判断页面是静态 HTML 还是动态渲染,再选择 BeautifulSoup、Selenium 或 Scrapy;采集后要做字段清洗、去重、失败重试和持久化。稳定爬虫的关键不是一次能抓到数据,而是页面结构变化、网络超时、反爬限制和部分字段缺失时仍然能恢复。

常见误区:

  • 直接写死脆弱 selector,没有 fallback。
  • 没有限速和重试,容易被封或丢数据。
  • 只保存原始数据,不做字段级质量检查。