Scrapy 2.17 测评:不走浏览器,直接调用 API

最后更新于 July 17, 2026
Scrapy 2.17 测评:不走浏览器,直接调用 API
AI 摘要
这篇 Scrapy 测评挑战了“它不支持 JavaScript,所以已经过时了”这一常见说法。测试结果表明,Scrapy 最擅长的场景是复现网页背后的 HTTP 或 JSON API,从而在不依赖浏览器的情况下输出干净、结构化的数据。文章覆盖了静态抓取、基于 API 的动态数据、错误处理、Feed 导出、安装成本,以及何时必须改用浏览器渲染。整体上,它把 Scrapy 描述为一个成熟、偏生产环境、以 HTTP 优先为核心理念的爬虫框架,而不是一个能直接解决所有 JavaScript 页面问题的通用工具。

因为 Scrapy 不运行 JavaScript,很多人就把它归到“搞不定现代网站”那一类。其实,这种印象正好反了。不渲染页面,本来就是它的核心思路;一旦你看懂它到底怎么工作,就不会再把这当成缺点了。

我用一次实测就把这点验证了。我搭了一个由 JavaScript 渲染的商品目录测试页,把 Scrapy 指向浏览器里能看到的页面,结果只抓回了 0 个商品卡片。后来我把同一个 spider 改成访问页面后台静默调用的 JSON 接口,结果干脆利落地拿到了 8/8 条数据。还是同一个工具,同一个会话,结果却完全相反——这篇测评要讲的,就是这两个数字之间的差别。

Scrapy 到底是什么,又不是什么

Scrapy 仅 HTTP 工作流

Scrapy 是一个用于抓取网站并提取结构化数据的 Python 框架。这也是维护者在 概览文档 里的官方定位。实际用下来,我觉得这个定义相当准确——没有任何需要修饰的营销话术。它已经足够成熟,也足够有分量,以至于当 Python 开发者问“严肃项目都用什么抓取工具”时,它几乎就是默认答案。仓库数据也能说明这一点:截至 2026-07-07scrapy/scrapy 大约有 62,981 个 GitHub stars、11,773 个 forks,以及 590 个 open issues。它采用 BSD-3-Clause 许可证,要求 Python 3.10 或更高版本,而我实际测试的版本是 2.17.0,正好就是测试当天上午发布的,所以这次连“版本太旧”这个借口都没有。

把它和新一代 AI 爬虫区分开的关键点只有一句:Scrapy 默认只走 HTTP。没有浏览器,也没有渲染引擎。它通过网络请求把 HTML 拉下来,再交给解析器,用 CSS 选择器或 XPath 去抽取字段。把这叫作“限制”有一半没错,但又没抓到它的设计初衷。Scrapy 的思路就是:对普通抓取任务来说,启动无头 Chrome 往往是走弯路;更聪明的做法,是找出页面本来就在请求的数据接口,然后直接去请求它。

这不是我替它硬解释。官方 动态内容文档 说得很清楚:先找出并复现底层数据请求,只有在没法复现的时候,才考虑无头浏览器。大多数爬虫会先打开浏览器,再去想 API;Scrapy 则把默认顺序反过来了。

关键功能,以及每项设计背后的取舍

从底层看,Scrapy 由一整套组件组成,而这些组件默认都在传达同一件事:你是开发者,你要的是控制权,不是“一键式向导”。

Spiders。 你写一个类,给它起始 URL,再定义一个 parse 回调,让它输出 item 或继续跟进链接。这比无代码提取器要多写一些,但换来的好处是:抓什么、往哪里抓,全都由你精确掌控。

Selectors。 解析层基于 parsel,而 parsel 底层又依赖 lxml。CSS 和 XPath 都是原生支持,不是后来硬补上去的。正因为有 lxml 做支撑,选择速度才快,抽取代码也更像在表达意图,而不是一堆字符串切片拼拼凑凑。

Feed 导出。 让 spider 对准一个文件,Scrapy 就能把 item 直接序列化成 JSON、JSON Lines、CSV 或 XML,不用你额外搭导出管线。我这次测试里,一个静态商品目录 spider 在同一次运行中直接输出了 JSON 和 CSV,我连一行导出代码都没写——feed export 的能力确实存在,而且完全符合文档描述。

AutoThrottle 和抓取控制。 请求由 Twisted 异步调度,你可以设置并发上限、下载延迟、深度限制、AutoThrottle 自适应限速,以及 robots.txt 规则遵守。这些控制项能避免大规模爬取变成服务器“轰炸机”。

把“只走 HTTP”重新定义成优势。 没有浏览器意味着更低内存、更高吞吐,也不用维护渲染引擎——前提是你要的数据确实可以通过普通 HTTP 拿到。现实里,这种情况比“浏览器优先”阵营想象得更常见。

安装:那种没法拍照留念的依赖堆栈

Scrapy 依赖堆栈

安装过程几乎没什么可说的,而对这么大的框架来说,这反而值得特地说一下。pip install Scrapy==2.17.0 在 macOS arm64 的全新虚拟环境里顺利完成,二进制 wheel 都能用,没有任何编译卡住的情况。没有戏剧化场面——但这正是重点。

不过,看看它到底拉下来了什么。scrapy version -v 显示 Scrapy 2.17.0 运行在 lxml 6.1.1、Twisted 26.4.0、pyOpenSSL 26.3.0 和 cryptography 49.0.0 之上,并由 parselcssselecttldextract 等组件共同组成完整栈。这是真正的“框架级体量”,不是一个单文件 HTML 解析器能比的。这台机器上所有依赖都有 wheel,所以安装过程轻松顺滑。换到其他环境,官方文档仍然会提醒你注意平台相关的依赖摩擦,历史上最容易出问题的往往就是 cryptographyTwisted 这一段,所以如果你用的是比较冷门的平台,最好提前留点处理时间。这里安装很顺,但你在上手前还是应该知道它会带来一整套框架级依赖,因为你拿到的就是一个框架,而框架本来就有框架的重量。

实测:哪些地方稳住了

Scrapy 实测结果

安装完成后,静态抓取这条路线表现很稳。召回完整,没有漏项。

测试结果耗时
本地静态商品目录 + 分页12/12 个商品0.557s
静态目录 CSV 导出写入 12 行(同一次运行)
文章提取标题 + 3/3 段正文0.416s
抓取图谱,DEPTH_LIMIT=20/1/2 层共 11 个页面0.904s
本地 500 页面捕获到 500 状态,未崩溃0.424s
Books to Scrape(公开站点)20 个商品2.053s
Quotes to Scrape spider(公开站点)12 条引用数据3.465s

静态商品目录 spider 从第一页一路翻到第二页,抓到了 12/12 条预期记录,并且在同一次运行中同时导出了 JSON 和 CSV。文章测试页更值得细看。Scrapy 并不会替你把页面自动整理成干净的 Markdown——它做的是让你用明确的选择器去定位 article 相关字段,同时把导航和页脚文本放进独立字段里。最后我拿到了 3/3 段正文,而且样板内容被隔离开了,没有混进输出。这个取舍很明确:选择器由你自己写,结果就会严格等于你要的内容,不会多也不会少。

抓取控制在小规模测试里也表现正常。开启 DEPTH_LIMIT=2、设置短下载延迟、按域名限制并发并遵守 robots.txt 后,抓取图谱在深度 0、1、2 之间共访问了 11 个页面,深度计数也完全符合预期。失败处理同样很平静。那个故意返回 500 的页面最终被作为一个结构化 item 交回,handle_httpstatus_liststatus 500 明确暴露出来——没有异常,也没有整个任务中断。Scrapy 认为错误状态码是你在 spider 逻辑里处理的对象,而不是会把整个爬取任务拖垮的意外。

实测:JavaScript 这堵墙,以及旁边那扇门

Scrapy JS 页面 0 节点 vs JSON API 8/8

接下来就是这篇评测的核心结果。

我把 Scrapy 的 HTTP 抓取器对准一个 JavaScript 渲染的商品目录测试页。它下载到了源 HTML,发现 0.product-card 节点,然后就继续往下走了——因为它没有运行本该把这些卡片绘制出来的脚本。公开的 Quotes to Scrape JS 页面 也讲了同样的故事:0 个渲染后的引用节点。测试如果停在这里,你很容易直接判定 Scrapy 不适合这个时代的任何站点。

但别停。

这个 JS 商品目录其实是由后台的 JSON API 填充的,绝大多数这类页面都是这样。于是我把同一个 Scrapy spider 指向那个接口,结果在 0.416s 内拿到了 8/8 个商品——没有浏览器,没有渲染,只是直接请求页面本来就在调用的 URL,再解析返回的 JSON。

这样的对比,几乎就是“复现请求”哲学的缩影。渲染后的页面只是个烟幕弹;真正的数据一直藏在 API 后面。Scrapy 的设计会把你引向直接命中那个接口,而不是花代价让无头浏览器坐在那里看页面自己拼出来。这样更快、更轻,也更不容易出错——相比前端 DOM 的千变万化,API 契约通常稳定得多。问题在于,这件事是手动的。你得自己打开 Network 面板,找到请求,再把它的 header 和参数复现出来。Scrapy 不会替你发现 API;它只是让你一旦找到之后,调用它变得非常简单。

这里也要说清楚两个边界。若页面确实没有可复现的底层请求——也就是数据完全由客户端渲染,背后没有 API——那就需要你自己接入无头浏览器,而这次测试我没有走这条路径。并且,上面所有结果都来自小型测试页和公开 demo 页面。我没有跑 100 到 1,000 页级别的大规模爬取,因此不会对内存、吞吐量或重试行为在大规模场景下的表现下结论——异步核心和抓取控制确实很有说服力,但说服力不是测量结果。

优缺点总结

优点:

  • 仅走 HTTP 的设计速度快、资源轻——静态页 12/12 的召回只用了大约半秒,JSON API 8/8 也只要 0.416s,没有浏览器开销。
  • “复现请求”的路线真的有效:一个 JS 页面在渲染层返回 0,但通过它背后的 API 能完整拿到全部 8 条。
  • 基于 lxml 的 CSS 和 XPath 选择器让抽取代码既清晰又高效。
  • 可直接导出 JSON/CSV/XML,无需额外编写导出管线。
  • 错误处理方式明确:500 状态会作为可捕获状态返回,而不是直接崩溃。
  • 抓取控制成熟:并发、延迟、深度限制、AutoThrottle、robots.txt 一应俱全。
  • BSD-3-Clause 许可证宽松友好;在现代环境里安装顺利。

缺点:

  • 设计上不渲染 JavaScript——客户端渲染页面会先表现为 0 节点,除非你自己找到 API。
  • 底层请求需要手动查找;Scrapy 不会替你定位接口。
  • 依赖栈比较重(Twisted、lxml、cryptography、pyOpenSSL、parsel、tldextract)——这次安装顺利,但在一些非典型平台上历史上确实容易出摩擦。
  • 需要写的代码比无代码或自动抽取工具更多;spider 得你自己维护。
  • 我的测试只覆盖了小型测试页和 demo 站点,没有验证超大规模爬取,所以大规模稳定性仍未证明。

适合谁,不适合谁

Scrapy 手动 API 边界

Scrapy 适合那些想要代码级控制、而且是按“请求”而不是按“页面”来思考的开发者。如果你看到一个卡顿的 JavaScript 站点,第一反应是“这里面肯定有个 API”,那这个工具就是给这种直觉准备的。它特别适合愿意写选择器、会看 Network 面板,并且愿意从头到尾自己掌控抽取逻辑的人。对于静态站点、分页目录,以及任何能找到 JSON 接口的页面,它都又快又准。

如果你不想把时间花在写和维护 spider 代码上,或者你的目标站点只是纯客户端渲染、没有可复现请求,而你又不想自己去接无头浏览器,那就可以考虑绕开它——或者至少和别的工具搭配使用。如果你想要的是:输入一个 URL,就直接得到干净的结构化结果,而不是自己写抽取规则,那从一开始就不是 Scrapy 的使命,它也从来没假装自己能做这件事。

替代方案,以及 Thunderbit 的位置

试试 Thunderbit 做网页数据提取

先说你要承担什么:这是一个免费、开源、需要你自己部署和维护的框架。你要自己负责 spider、依赖栈,以及为每个站点寻找数据请求的工作。作为交换,你不需要按请求付费,所有东西都留在自己手里,而且控制权完全在你这边。对很多团队来说,这就是正确选择,这篇测评也不是要劝谁放弃它。

真正的取舍点在于“渲染与漂移”这个问题,而 Scrapy 的回答是:这个问题由你来解决。你去找 API,你去复现请求,你去通过自己接入浏览器来处理“没有 API”的情况。相比之下,托管式 AI 抓取 API 会把这一层直接替你拿掉。对技术读者来说,Thunderbit 的开发者栈就在这个位置——它提供的是 AI 抓取 API、MCP server 和 CLI,而不是销售和运营团队用的浏览器插件。POST /distill 可以把页面转换成适合 LLM 处理的干净 Markdown;POST /extract 可以按你定义的 schema 返回结构化 JSON;两者都在服务端处理 JavaScript 渲染、反爬和动态内容——包括 Scrapy 需要你自己想办法用浏览器处理的客户端渲染场景。它还提供给 AI agent 和编程助手使用的 MCP server(并带有一个免费的 thunderbit_suggest_fields,可在你付费前先帮你梳理页面字段),以及可通过 npx @thunderbit/thunderbit-cli 调用的 CLI,适合终端、CI 或定时任务。

差别不在质量,而在“责任归属”。Scrapy 是一个明确的工程框架:你维护 spider、pipeline 和 JavaScript 策略,换来的是零单次调用成本下的完全控制。Thunderbit 的栈则把渲染与提取这一层交给托管服务,你不用再钻 Network 面板,也按调用次数付费。规模小、代码优先、又愿意亲自掌控每一步?Scrapy 的控制力更合适。要跨一百个站点扩展,而且你不想为每个站点手动复现请求?那托管方案就能省掉整整一大类工作。

如果你想了解更广泛的生态,这些基准评测可以顺手看一下: 开源爬虫完整对比Colly 无浏览器 Go 爬虫测评、以及 Scrapling 自适应选择器测评

结论

Scrapy 值得用吗?值得——前提是你是想要控制权的开发者,并且认同它的世界观:别渲染页面,去找页面背后的请求。测试结果证明,这套哲学确实像它宣传的那样有效。一个 JavaScript 商品目录在 HTTP 抓取器面前只返回 0 个卡片,而为它供数的 JSON API 却让同一个 spider 一口气拿到了全部 8 条数据。静态提取做到了 12/12,文章选择器把 3/3 段正文和样板内容分得清清楚楚,抓取图谱在 11 个页面内严格遵守深度限制,而 500 状态也只是一个被处理掉的状态,不会导致崩溃。

不过,评价也要放在正确的尺度上。Scrapy 不会渲染 JavaScript,也不会替你找 API——这一步得靠你自己建立反射。依赖栈是典型框架级体量,在某些奇怪平台上仍可能出问题,即使我这次环境很顺。再加上我测的是测试页和 demo 页,不是上千页的大爬取任务,所以规模能力只能说“前景不错”,不能说“已经证实”。在这些边界之内,Scrapy 是一个最坚定拥抱某种 quietly radical 理念的工具:穿过网页最快的方式,往往根本不是“走进”网页本身。

试试 Thunderbit 做网页数据提取 Get Started Free

常见问题

Scrapy 能抓取 JavaScript 渲染的页面吗? 默认的 HTTP 抓取器不能——在一个 JS 测试页和公开的 Quotes JS 页面上,它都只返回了 0 个节点,因为它只是下载 HTML,并没有运行浏览器。官方建议的做法,是找出页面背后的底层数据请求并直接请求它;在我的测试中,JS 商品目录背后的 JSON API 完整返回了 8 条数据。如果页面根本没有可复现的请求,那就需要你自己接入无头浏览器。

“复现请求”到底是什么意思? 大多数动态页面都会在后台通过 JSON API 加载数据,然后再由客户端渲染出来。与其让浏览器把整个过程演给你看,不如打开 Network 面板,找出那个 API 调用,再把 Scrapy 直接指向它。这样比渲染更快也更稳定——API 契约通常比 DOM 结构更少变动——但这一步需要手动操作,Scrapy 不会替你自动定位接口。

Scrapy 安装起来难吗? 对我来说很顺利——在 macOS 的全新虚拟环境里,pip install Scrapy==2.17.0 通过二进制 wheel 完成,没有编译错误。但它会拉入一整套较大的依赖栈(Twisted、lxml、cryptography、pyOpenSSL、parsel、tldextract),而且官方文档仍提醒某些系统可能有平台相关的依赖摩擦,所以如果你用的是比较特殊的环境,最好预留这部分时间。

Scrapy 支持哪些输出格式? 它原生支持 JSON、JSON Lines、CSV 和 XML。只要把 spider 指向文件,就能自动序列化 item,不需要额外代码。我这次测试里,一个 spider 在一次运行中同时输出了 JSON 和 CSV。需要注意的是,它导出的是你选择的字段,不会自动把页面整理成 Markdown。

Scrapy 可以免费用于商业项目吗? 可以,它使用的是 BSD-3-Clause 许可证,宽松且适合商业使用。不过,在实际基于它开发之前,还是建议你去 仓库 再确认一下当前许可证状态。同时也要负责任地设置 user-agent、代理和限速策略——能做什么,不代表应该无节制地做什么。

Ke
Ke
Thunderbit 首席技术官 | 高级数据科学家与机器学习专家 Ke Shen 拥有近十年的机器学习和数据科学经验,毕业于哥伦比亚大学,曾任 Walmart Labs 高级数据科学家。他在 Python、R、Java 和统计学方面拥有深厚且备受同行认可的专业能力,并分享如何将复杂的 AI 算法从理论落地到生产级架构的实战经验。
目录
Thunderbit · AI 网页数据代理

1 次点击 中从任何页面提取数据

受到超过 250,000+ 用户的信赖
提供免费计划
使用 AI 提取数据
轻松将数据传输到 Google Sheets、Airtable 或 Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week