用一个可运行项目上手 Scrapy 2.19:从 Spider 到数据导出

2026-09-28 26 预计阅读时间: 1 分钟
来源: oschina.net AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:9 分钟

Scrapy 橙皮书已围绕 Scrapy 2.19 更新,并继续采用实例驱动的方式讲解框架核心。对开发者来说,这类教程的价值不只是列出 API,而是把请求调度、页面解析、数据导出和限速配置串成一条完整链路。

下面不依赖在线站点,直接用本地 HTTP 服务搭建一个可重复运行的小项目。

Scrapy 项目真正解决了什么

一个最小爬虫似乎只需要“发送请求并解析 HTML”,但生产任务通常还包含这些问题:

  • 哪些 URL 已经抓取,哪些请求正在排队;
  • 请求失败后是否重试,超时如何处理;
  • 如何限制并发和抓取频率;
  • 解析出的字段怎样清洗、校验和持久化;
  • 网站结构变化后,如何定位失效的选择器。

Scrapy 将这些职责拆分给 Engine、Scheduler、Downloader、Spider、Item Pipeline 等组件。Spider 更适合专注于两件事:生成后续请求,以及把响应转换成结构化数据。调度、下载、重试和导出则交给框架或扩展组件处理。

这种分工也是阅读实战型教程时应抓住的主线:不要只记 response.css() 的语法,而要理解一条 Item 是如何从 URL 一路流向输出文件的。

搭建一个可重复运行的本地爬虫

下面假设使用 Bash,并且本机已经安装 Python。安装时将 Scrapy 限定在 2.19 系列,避免未来升级导致示例行为变化:

mkdir scrapy-219-demo
cd scrapy-219-demo

python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install 'Scrapy>=2.19,<2.20'

scrapy startproject orange .
mkdir -p site

Windows PowerShell 激活虚拟环境时,可将 source .venv/bin/activate 替换为:

.venv\Scripts\Activate.ps1

创建一个本地测试页面 site/index.html:

<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <title>Scrapy 本地测试页</title>
</head>
<body>
  <article class="quote">
    <p class="text">框架负责流程,Spider 负责业务规则。</p>
    <span class="author">Alice</span>
    <a class="tag" href="/tags/python">Python</a>
    <a class="tag" href="/tags/scrapy">Scrapy</a>
  </article>
  <article class="quote">
    <p class="text">可观测的爬虫比能运行的爬虫更容易维护。</p>
    <span class="author">Bob</span>
    <a class="tag" href="/tags/engineering">Engineering</a>
  </article>
</body>
</html>

在 orange/spiders/quotes.py 中编写 Spider:

import scrapy


class QuotesSpider(scrapy.Spider):
    name = "quotes"
    allowed_domains = ["127.0.0.1"]
    start_urls = ["http://127.0.0.1:8000/index.html"]

    def parse(self, response):
        for quote in response.css("article.quote"):
            yield {
                "text": quote.css("p.text::text").get(default="").strip(),
                "author": quote.css("span.author::text").get(default="").strip(),
                "tags": quote.css("a.tag::text").getall(),
                "source_url": response.url,
            }

打开第一个终端,启动本地 HTTP 服务:

cd scrapy-219-demo
source .venv/bin/activate
python -m http.server 8000 --directory site

再打开第二个终端运行爬虫:

cd scrapy-219-demo
source .venv/bin/activate
scrapy crawl quotes -O output.jsonl
cat output.jsonl

-O 会覆盖旧文件,适合反复调试;如果需要追加输出,可以使用小写的 -o。JSON Lines 每行保存一个对象,便于流式处理和逐条排查错误。

预期输出类似:

{"text":"框架负责流程,Spider 负责业务规则。","author":"Alice","tags":["Python","Scrapy"],"source_url":"http://127.0.0.1:8000/index.html"}
{"text":"可观测的爬虫比能运行的爬虫更容易维护。","author":"Bob","tags":["Engineering"],"source_url":"http://127.0.0.1:8000/index.html"}

从示例走向长期运行任务

本地页面没有延迟、封禁和结构漂移,真实网站则完全不同。可以在 orange/settings.py 中加入一组保守配置,再根据目标服务的承载能力调整:

ROBOTSTXT_OBEY = True

CONCURRENT_REQUESTS_PER_DOMAIN = 2
DOWNLOAD_DELAY = 1.0
DOWNLOAD_TIMEOUT = 20
RETRY_TIMES = 2

AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_START_DELAY = 1.0
AUTOTHROTTLE_MAX_DELAY = 10.0
AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0

FEED_EXPORT_ENCODING = "utf-8"
LOG_LEVEL = "INFO"

这些配置不是“抓得越慢越好”,而是在吞吐量、稳定性和对目标服务的影响之间取得平衡。尤其需要注意:

  1. 遵守 robots.txt 和站点条款。 技术上能够访问,不代表业务上或法律上允许采集。
  2. 为选择器准备测试。 页面把 article.quote 改名后,爬虫可能不会报错,只会静默地产出零条数据。
  3. 对关键字段做校验。 作者、价格、时间等字段缺失时,应明确丢弃、补默认值或记录异常。
  4. 固定依赖版本。 完成验证后,可用 python -m pip freeze > requirements.txt 保存环境。
  5. 观察统计信息。 关注响应状态码、重试次数、抓取条数和日志错误,而不只是输出文件是否生成。

例如,可以先用 Scrapy Shell 单独验证选择器,不必每次启动完整任务:

scrapy shell http://127.0.0.1:8000/index.html

进入交互环境后执行:

response.css("article.quote").getall()
response.css("article.quote span.author::text").getall()

这比在 Spider 中反复修改、运行和查看文件更快,也能清楚区分“请求没有成功”和“选择器没有匹配”两类问题。

文档源码也值得纳入开发流程

从目录结构看,教程使用 Sphinx 管理文档源文件,并将配置放在 doc/conf.py。如果下载了对应项目,可以这样尝试在本地构建文档;具体依赖文件名应以仓库实际内容为准:

python -m venv .docs-venv
source .docs-venv/bin/activate
python -m pip install sphinx
sphinx-build -b html doc doc/_build/html
python -m http.server 8080 --directory doc/_build/html

本地构建的优势是可以全文搜索、修改示例,并让文档版本与项目代码保持一致。若项目额外使用主题或 Sphinx 插件,还需要安装其文档依赖。

采用 Scrapy 2.19 前的检查清单

Scrapy 适合多页面抓取、请求调度、并发控制和结构化数据导出。如果任务只是请求一个固定 API,requests 或 httpx 可能更轻;如果页面必须执行大量 JavaScript,则需要评估浏览器自动化方案,或将其与 Scrapy 的调度能力组合使用。

开始实际项目之前,建议确认:

  • Python 与 Scrapy 2.19 的运行环境已经独立并锁定;
  • 已获得必要的抓取许可,并设置合理频率;
  • Spider 只承担请求生成和页面解析职责;
  • 关键选择器与字段有测试或告警;
  • 输出采用可恢复、可追踪的格式;
  • 已记录失败请求、重试和状态码分布。

先让一个本地、确定性的例子完整跑通,再逐步接入真实网站、Pipeline 和持久化系统,通常比一开始就堆叠代理池、分布式调度和浏览器渲染更稳妥。


相关推荐