自适应选择器经常被错算到别的工具头上。我看过一半以上的爬虫对比文章,都把“网站改版后还能正常跑”这个能力挂在某个大名鼎鼎的 AI 爬虫身上,但它其实并不是真的能做到。真正把这个功能摆在台面上的 Python 库是 Scrapling,这是一个增长很快的项目,截至 2026-07-09,GitHub stars 大约有 68.7k。
所以我做了一个最关键的测试。先搭了一个固定测试页,保存一个选择器,然后把目标元素的 class 名改掉——这正是最容易让爬虫在网站改版后第二天悄悄失效的那种变化。普通选择器返回空结果,而 Scrapling 的自适应匹配仍然找到了目标元素。这个能力确实存在,下面我会展示数据。更少人会去量化的是:它到底能恢复到什么程度,而这条边界,恰恰就是这篇评测的核心。
Scrapling 到底是什么

Scrapling 自称是一个自适应网页抓取框架,能处理“从单次请求到大规模爬取”的各种场景。去掉宣传语之后,它本质上是两层组合:一层是负责拉取页面的 HTTP Fetcher,另一层是基于 lxml 的 Selector 解析器,支持标准 CSS/XPath,也支持很方便的 ::text 和 ::attr() 伪选择器。它采用 BSD-3-Clause 许可证,属于开源里相当宽松的那一类。我测试的是 0.4.10 版本,也就是当时的最新版——不用担心“你测的是老版本”这种问题。
真正有意思的是它上面那层自适应能力。可以把普通选择器想成一个写死的门牌号:“抓取 class 为 product-name 的元素。”一旦楼号变了——也就是 class 名改了——这个地址就会指向空地。Scrapling 可以在第一次运行时保存某个元素的特征指纹,等下一次页面结构变化后,再根据指纹把这个元素重新定位回来,而不是依赖已经失效的地址。按照 Scrapling 自适应抓取文档 的说明,匹配阶段会综合元素标签、文本、属性、兄弟节点和位置来计算相似度——没有模型参与,就是拿它保存过的结构做比对。
这里要把来龙去脉说清楚,因为这会影响你怎么看这个功能。自适应重定位确实是真实存在、而且有文档说明的能力,不是我“发现”的新玩意儿——官方文档已经把保存到 SQLite、再按相似度匹配这一整套机制讲得很明白,第三方文章也有类似介绍。自愈选择器这个概念在测试自动化领域里也早就存在。Scrapling 的独特点在于:它把这个功能作为原生库能力直接提供出来。像 lxml、parsel 和 BeautifulSoup 这类普通解析库只能给你静态选择器,不会自己帮你重定位。所以这是一个我亲测并做了压力验证、但并不是“别人都没有”的能力。
自适应测试的详细过程

测试环境是这样的:我搭了一个商品目录,用 class 为 product-name 的元素进行跟踪。然后我把这个 class 改成了 product-title,再用同样的代码重新跑。普通的 .product-name 选择器只匹配到 0 个元素——这正是你会预期到的结果,因为它指向的 class 已经不存在了。Scrapling 的自适应重新匹配则利用之前保存的指纹,把这个元素重新找了回来。原始结果可以在基准仓库的 local_adaptive_selector.json 中看到。


接下来是很多评测都会略过的部分。我又做了一个合成的多元素测试——不是一个,而是三个被跟踪的元素。结果 Scrapling 只重新定位回来了第一个保存的元素,并没有把三个都找回来。这不是失败,也不是 bug;文档把自动匹配描述成对单个元素的追踪,每个保存的元素都有自己的指纹,所以在默认设置下出现 1/3 的结果,正好说明它是按设计运行的。但这也意味着,准确的表述应该是“更有韧性的元素追踪”,而不是“整个改版页面的自动恢复”。自动匹配会跟着你指定的那个元素走;多个元素一起恢复,需要你自己额外调优。
这个区别比表面上看起来更重要。“能扛住页面结构变化”是一个很吸引人的标题;“能持续跟踪你指定的那个带指纹的元素,在结构变化后依然找得到它,剩下的要你自己处理”才是你真正买到的能力。如果你按前者预期,可能会失望;按后者理解,它就能稳稳干活。
安装过程:没人提醒你的坑
这一点我是真的花了时间踩坑,所以先告诉你,免得你再重复。pip install scrapling 装下来的只有解析器——真的只有解析器。只要我写了 from scrapling.fetchers import Fetcher,马上就会报一串缺失依赖:先是 curl_cffi,接着是 playwright,然后是 browserforge,每解决一个才会冒出下一个。
正确做法是安装额外组件:pip install "scrapling[fetchers]",或者运行 scrapling install 这个 CLI 命令,它会把完整的 HTTP + 浏览器抓取器栈一起拉下来。这样之后,一切都正常了。但“基础安装看起来没问题,第一次 fetch 才炸”这条路径是真的,官方前置说明里也完全没把这事摆到最显眼的位置。第一次命令就把 [fetchers] 额外依赖和它那一长串传递依赖算进去,你就能少走很多弯路。
在纯 HTTP 抓取里表现如何
抓取器装好后,普通抽取流程表现得很稳定——召回率直接是 1.0:
| 测试 | 结果 |
|---|---|
| 静态目录 + 分页 | 12/12 个商品 |
| 文章抽取 | 标题 + 3/3 段落 |
| 动态 JSON API | 8/8 个条目 |
| Books to Scrape(公开页) | 20 个商品 |
| HTTP 500 处理 | 正常暴露状态码,无崩溃 |
这里能看出 lxml 的底子很好。CSS 和 XPath 的行为都很符合预期,而 ::text / ::attr() 这类伪选择器也让抽取代码更短、更清晰,不会写成一堆嵌套调用。500 状态码这个例子虽然小,但很能说明问题——Fetcher 直接把状态码暴露出来,而不是给我抛一长串堆栈,这就是“能进生产定时跑”的爬虫和“得有人盯着”的爬虫之间的差别。完整数据在 scrapling-test-summary.json 里。
这些都不花哨。只是正确,而正确这件事往往被低估。
它不做什么,以及为什么不做

HTTP Fetcher 不会渲染 JavaScript。我把它指向一个 JS 渲染的测试页,结果返回 0 个卡片;在公开的 Quotes to Scrape JS 页面 上也是同样的 0。这不是缺陷——HTTP Fetcher 只是下载 HTML,它不会驱动浏览器,所以客户端渲染的内容在它看来根本不存在。Scrapling 另有一个面向 JS 页面、基于浏览器的 DynamicFetcher。这次我没有测它,所以不评价它的表现。只是别把 HTTP 路径丢到前端渲染应用上,还期待它能看见内容。
另外还有一个面向反检测的 StealthyFetcher。我把它视作合规性问题,仅此而已——不是拿来炫耀的功能。你在哪里、以什么方式抓取,是否允许,取决于你自己的法律边界;这篇评测测试的是抽取能力,不是规避能力。我没有运行它,也不会给它打分。
优缺点
优点:
- 自适应选择器确实能在 class 改名后把跟踪元素找回来;普通选择器则会变成 0——这就是选 Scrapling 的核心理由。
- 在静态页面、文章页和 JSON API 上,HTTP 抽取召回率达到 1.0。
- 基于 lxml 的 CSS/XPath 很干净,
::text/::attr()伪选择器也很易读。 - HTTP 500 处理很稳:状态码能正常暴露,不会崩。
- 测试版本就是最新发布版,没有版本落后的问题。
- BSD-3-Clause 许可证宽松,适合商用。
缺点:
- 自动匹配只跟踪一个已保存元素,不会自动恢复整页——三个元素测试只恢复了一个,宣传时要把这个范围说清楚。
pip install scrapling只装解析器;抓取器需要[fetchers]额外依赖,以及那条很重的依赖链,这点我踩坑后才知道。- HTTP Fetcher 不渲染 JavaScript;客户端内容需要用浏览器版
DynamicFetcher,而我这里没测它。 - 这个“强韧性”卖点在多元素场景下仍然需要手动调优。
适合谁,不适合谁
如果你维护的爬虫经常面对改版网站,而且已经厌倦了某个 class 名一变就把抽取结果悄悄清零,那 Scrapling 很值得放进工具箱。假如你最头疼的问题是“选择器隔几周就坏,我只想让那个关键元素一直能找到”,那它就是冲着这个场景来的。就算你从不启用自适应层,它也能作为一个干净、轻量的 lxml 抽取器,胜任静态页面和 JSON API。
但有两类情况,你要重新调整预期,或者直接去看别的方案。第一,如果你希望自适应选择器能把整个改版后的页面自动修复好——它追踪的是元素,不是重建布局——那你需要换一种心智模型。第二,如果你的目标站点 JavaScript 很重,而且你又不想部署浏览器驱动的 DynamicFetcher,那单靠 HTTP 路径是够不到的。不管哪种情况,真要安装,第一条命令就把 [fetchers] 额外依赖加上。
托管式 AI 抓取 API 适合放在哪一层
Scrapling 是一个免费的开源库,需要你自己运行和维护。代码、依赖链、调优都归你所有,作为交换,你不用为每次请求付费,也能把一切留在内网。这是一个很现实、也很有说服力的选择,对很多团队来说,这正是正确答案。
值得思考的问题是:韧性问题到底该由谁来负责。Scrapling 的答案是:由你负责。你自己给元素打指纹、自己做调优。而托管式 AI 抓取 API 的思路不一样——结构变化的处理交给服务端。Thunderbit 的开发者方案正好填的是这个位置。POST /extract 会按你定义的 JSON Schema 返回结构化 JSON,渲染、反爬和页面结构漂移都由服务端吸收;renderMode 参数则控制在抽取前页面要执行到什么程度。Thunderbit 还提供面向 AI 智能体和编程助手的 MCP server,thunderbit_suggest_fields 先免费运行,用来规划抽取字段;同时也提供 npx @thunderbit/thunderbit-cli 这个 CLI,适合终端、脚本和 CI。三种入口背后用的是同一套 AI 引擎。
真正的取舍并不是“谁更好”,而是你希望韧性逻辑放在哪里。用 Scrapling,你把这部分留在自己的代码里,由你自己做指纹和调优,单次调用成本为零,但你也要承担维护工作。用托管 API,你把结构变化处理交给平台,并按请求付费。如果你规模不大、喜欢自托管、也愿意自己掌控调优,那 Scrapling 的控制力正合适。如果你要同时跑上百个站点,又不想逐个维护选择器指纹,那托管方案就能把这类维护工作直接消掉。
如果你在横向对比,可以看看 完整开源爬虫基准测试,里面把 Scrapling 和其他工具放在同一套测试样本里比较;另外,Scrapy 评测 和 Colly 评测 也覆盖了另外两个值得关注的 HTTP 优先框架。
结论
Scrapling 值不值得用?值得——如果你想要一个开源 Python 抽取库,它最突出的本事是:在底层结构变动后,仍然能把你跟踪的那个元素找回来,而且你清楚这项能力的边界。它确实能在一个普通选择器已经失效的改名场景下,把元素重新找回,而这个变化足以让常规爬虫悄悄丢数据。纯 HTTP 抽取很干净,在所有测试样本上都拿到了满召回。许可证宽松,我测的版本也是最新版。
只要把能力边界理解正确,你就会很满意它。它追踪元素,但不会自动重建页面——三个元素测试只恢复了一个。安装时从第一条命令就加上 [fetchers],否则你就会像我一样撞上依赖墙。如果你的页面需要 JavaScript,那该由浏览器版抓取器负责,不是 HTTP 版。把这些边界都看清楚后,Scrapling 就能稳定完成它最擅长的那件事;在 Python 爬虫库里,它也是少数真正把大家口口相传的功能做出来的工具之一。
试用 Thunderbit 进行网页数据提取 Get Started Free
常见问题
Scrapling 的自适应选择器真的能扛住网站改版吗?
它确实能在我测试中扛住某个已跟踪元素的 class 改名。把 product-name 改成 product-title 之后,普通选择器匹配到 0,而自适应重新匹配把那个元素找回来了。但它追踪的是已保存的元素,不是自动重建整页:在一个三个元素的合成测试里,只恢复了一个。所以更准确的说法是“更有韧性的元素追踪”,而不是“整页自动恢复”。
为什么 pip install scrapling 后,一导入 fetcher 就报错?
因为基础安装只包含解析器。导入 scrapling.fetchers 时,会连锁触发缺失依赖:先是 curl_cffi,然后是 playwright,再到 browserforge。运行 pip install "scrapling[fetchers]"(或者执行 scrapling install CLI)把完整抓取器栈装上,导入就能正常工作。
Scrapling 能抓 JavaScript 渲染的页面吗?
HTTP 版 Fetcher 不行——无论是 JS 测试页,还是公开的 Quotes JS 页面,它都返回 0,因为它只下载 HTML,不执行浏览器。Scrapling 另外提供了基于浏览器的 DynamicFetcher 专门处理 JS 页面,但这次测试没有覆盖它,所以我暂时不评价它的性能。
Scrapling 做常规抽取时快不快、准不准? 测试里它很准确:在静态目录、文章页和 JSON API 上召回率都是 1.0,而且基于 lxml 的 CSS/XPath 也很干净。它还把 HTTP 500 正常暴露出来,而不是直接崩溃。即使你完全不用自适应层,它依然是一个适合静态内容的轻量抽取器。
Scrapling 可以商用吗? 可以,它采用 BSD-3-Clause 许可证,宽松且适合商用。不过在正式采用前,最好还是先到 repo 上确认当前许可证状态。


