Skip to content

Scrapy实战

真正做项目时,你不会只写一个 Spider 文件就结束。

你会逐渐遇到这些更真实的问题:

  • 页面是动态渲染的
  • 请求必须带特定头信息
  • 某些接口是 POST 请求
  • 不同请求要带不同 Cookie
  • 部分逻辑要在请求发出前或响应回来后插入处理

这时候,你就会开始从“会用 Scrapy”进入“会做 Scrapy 项目”的阶段。

本节目标

  • 理解 Scrapy 实战中常见的真实问题
  • 理解中间件的作用
  • 理解 Selenium 在动态页面中的定位
  • 学会给请求增加请求头和 Cookie
  • 理解随机请求头和 POST 抓取的基本思路

实战和教程例子的区别

教程里你经常会看到:

  • 一个起始地址
  • 一个 XPath
  • 一次请求
  • 一次输出

但真实项目往往不是这样。你真正面对的页面通常更复杂:

  • 数据不一定直接在 HTML 里
  • 页面不一定一次请求就拿全
  • 请求不一定是 GET
  • 返回不一定总是稳定

所以实战阶段最重要的,不是记更多 API,而是学会分析请求链路和处理复杂情况。

中间件是什么

Scrapy 中间件可以理解成:

  • 在请求发出去之前插入处理逻辑
  • 在响应回来之后插入处理逻辑

它常见用途包括:

  • 动态加请求头
  • 动态加 Cookie
  • 设置代理
  • 和 Selenium 配合

为什么中间件重要

因为有很多操作并不适合直接写死在 Spider 里。

例如:

  • 每次请求都要加同一个头
  • 不同请求要切换不同 User-Agent
  • 要统一处理某类响应

如果这些都塞进 Spider,代码会很快变乱。

添加请求头

你可以在单个请求中直接写:

python
yield scrapy.Request(
    url="https://example.com",
    headers={
        "User-Agent": "Mozilla/5.0"
    }
)

这适合简单场景。

如果项目里大量请求都需要统一处理,更常见的方式是放进中间件或 settings。

有些页面依赖登录状态或会话信息。

python
yield scrapy.Request(
    url="https://example.com/profile",
    cookies={
        "sessionid": "abc123"
    }
)

如果 Cookie 不对,返回内容很可能不是你真正想要的页面。

随机请求头

很多网站会根据请求头判断访问行为是否异常。

如果所有请求的 User-Agent 都完全一样,而且访问频率还很高,就更容易暴露机器特征。

一个基础思路是准备一组 User-Agent:

python
user_agents = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)",
    "Mozilla/5.0 (X11; Linux x86_64)"
]

然后随机取一个给请求使用。

Selenium 的定位

有些页面的数据严重依赖 JavaScript 渲染。

这时你直接请求原始 HTML,可能只能拿到一个空壳页面。

比如页面源码里几乎没有真正数据,但浏览器打开后内容却很多,这往往说明:

  • 页面数据是后续异步请求加载的
  • 或者页面依赖浏览器执行 JavaScript

这时候 Selenium 的价值就出现了。

你可以把 Selenium 理解成:

  • 让程序去控制一个浏览器

它比普通请求更重,但在动态页面场景中很有用。

POST 请求在实战中的意义

很多初学者会下意识认为爬虫就是 GET 请求,其实不是。

很多接口:

  • 登录接口
  • 搜索接口
  • 分页接口
  • 提交型接口

都可能是 POST。

Scrapy 中写 POST 请求的基础方式是:

python
yield scrapy.FormRequest(
    url="https://example.com/login",
    formdata={
        "username": "tom",
        "password": "123456"
    },
    callback=self.parse_login
)

这表示:

  • 发起 POST 表单请求
  • 带上表单参数
  • 请求完成后交给 parse_login 处理

一个更贴近实战的流程示例

假设你要抓一个登录后可见的课程列表页面,思路可能是:

  1. 先分析登录请求是不是 POST
  2. 确认用户名、密码参数名是什么
  3. 发登录请求
  4. 拿到登录成功后的状态
  5. 再访问课程列表页面
  6. 解析课程标题和链接

这已经不是“抓一个静态页”的难度了,但思路是连贯的。

中间件 + 请求头的一个简单思路

假设你想让每个请求都自动带上一个浏览器标识,可以在中间件中统一处理。

你不用现在就把完整中间件细节全背下来,但至少要知道:

  • 某些共用逻辑适合放中间件
  • 中间件能让 Spider 更专注于抓取逻辑本身

实战中的真正重点

很多人以为实战的重点是“记住更多框架用法”,其实不是。

真正重点是:

  • 请求该在哪里发
  • 响应该在哪里解析
  • 数据该在哪里保存
  • 哪些逻辑是单个请求的
  • 哪些逻辑应该抽到全局配置或中间件

这是项目意识,而不是 API 背诵。

常见错误

1. 页面抓不到,就立刻怀疑 XPath

其实更常见的真实原因可能是:

  • 页面是动态加载的
  • 请求头不对
  • Cookie 丢了
  • 应该 POST 却写成了 GET

2. 把所有逻辑都堆在 parse()

这会导致代码很快失控。

3. 用 Selenium 解决一切问题

Selenium 很强,但也很重。能直接抓接口,就不要上浏览器自动化。

4. 没先分析请求过程就开始写代码

正确顺序应该是:

先观察浏览器行为,再决定 Scrapy 应该怎么写。

练习题

练习 1

写一个 Scrapy 请求,手动加上 User-Agent

练习 2

写一个带 Cookie 的请求,思考它适用于什么场景。

练习 3

尝试写一个 FormRequest,模拟最简单的 POST 请求。

练习 4

找一个动态页面,观察它是不是先加载 HTML 再请求接口。

练习 5

自己总结:哪些逻辑适合写在 Spider 中,哪些逻辑更适合写在中间件或配置里。

本节小结

Scrapy 实战阶段最重要的,不是学会更多命令,而是开始理解真实抓取项目中问题会出现在哪里。

你这一节最重要的收获应该是:

  • 知道中间件是干什么的
  • 知道 Selenium 为什么会出现
  • 知道请求头、Cookie、POST 在实战里为什么重要
  • 开始建立“请求、解析、保存、配置分层”的意识

只要这层意识建立起来,你就不再只是会写例子,而是开始接近真正的爬虫项目开发。

Built with VitePress.