一些第三方爬虫对比文章把“自适应智能”——也就是能学习站点、并在页面结构变化后自动修复选择器——归功于 Crawl4AI。但在我测试过的 API 范围里,并没有观察到这种行为。Crawl4AI 实际提供的是基于浏览器的 Markdown 生成,以及 CSS/XPath 提取。Scrapling 则提供了独立的自适应选择器功能,不过它也有自己评测里写明的使用边界。

我用 Crawl4AI 0.9.0 跑了五类有明确标准答案的页面:静态目录页、JavaScript 渲染目录页、带大量模板内容的文章页、故意返回 500 的页面,以及一个带链接的多页图谱。测试中的 Markdown 路径和 schema 路径都返回了预期的 fixture 内容。原始 Markdown 会保留模板噪音,深度爬取需要针对页面设置等待条件,而普通的 500 错误则被打上了类似反爬的错误标签。
Crawl4AI 到底是什么
先说一个很多人在安装时会搞错的点。Crawl4AI 不是一个轻量级 Python 解析器。第一次运行 crawl4ai-setup 时,它会悄悄拉下两整套浏览器组件——Playwright 和 Patchright——一旦你看到这一点,整个工具的定位就清楚了:它本质上是一个受控的无头浏览器,上面再套了一层 Markdown 转换器,披着爬虫的外衣。
官方上,它是一个开源、Apache-2.0 许可的库,目标是把网页转换成 Markdown,用于 RAG 流水线、智能体和数据工作流。我测试的是 v0.9.0。它的核心原语包括 AsyncWebCrawler、BrowserConfig、CrawlerRunConfig、Markdown 生成,以及基于 CSS/XPath 或 LLM 的提取策略,具体可参考官方快速开始。
真正重要的心智模型是这样的:大多数解析库是发起 HTTP 请求,然后解析返回的字节;而 Crawl4AI 则是直接驱动真实浏览器。它自带浏览器渲染能力,所以安装成本比纯 HTTP 解析器高,但对于异步渲染出来的元素,可靠提取时仍可能需要显式等待。我这里测试的内容里,没有任何一项会在页面改版后自动重写选择器。除非有明确的官方来源和可复现的 API 证明,否则把“自我修复”这件事视为第三方对比文案的误读更稳妥。
关键功能,以及背后的工作方式
单页抓取是它最核心的能力。你把 URL 交给 AsyncWebCrawler,它会在浏览器里加载页面,然后返回 Markdown。在官方的 example.com 快速开始示例里,这个往返耗时 1.81 秒,并返回了干净的 200 状态。没有什么花活,但它说明最基本的流程确实能在几乎零配置下跑通——不需要 schema,不需要等待条件,也不需要额外浏览器配置。
视频教程(1:02:38):Crawl4AI 官方教程,含完整 1 小时快速开始示例。
结构化提取是第二根支柱,也是 Crawl4AI 最接近“理解页面”的地方——严格来说,并不是推理,而是你自己定义一个 schema。它不是只吐 Markdown,而是让你通过 JsonCssExtractionStrategy 提供 CSS schema,然后返回你指定字段的 JSON 对象。在我本地的静态目录页上,它返回了 6 条干净的 JSON 记录——产品名、分类、价格、评分、详情页 URL——与预期的 6 个商品完全一致。这就是“把页面当文本返回”和“把数据按行返回”的区别,而 Crawl4AI 可以在同一次抓取里同时做到这两件事。不过,选择器仍然得你自己写;工具只会匹配你给它的内容,不会帮你自动推断 schema。

动态渲染是浏览器能力真正派上用场的地方。把它指向一个 JavaScript 渲染的目录页,并设置 wait_for="css:.product-card",它就会等到客户端渲染完成后再提取。在我本地的 JS fixture 上,无论是 Markdown 还是 schema 输出,都达到了 8/8 商品召回,耗时约 1.56 秒。在公开的 Quotes to Scrape JS 页面 上,它抓到了渲染后的引文,并保存了可用截图——这是普通 HTTP 请求永远看不到的内容,因为初始 HTML 里根本没有可解析的数据。
接下来是规模化和爬取。arun_many() 并发跑了 6 个本地详情页,完整达成 6/6 召回,用时 3.76 秒。Crawl4AI 还提供深度爬取策略——BFS、DFS、BestFirst——可以沿着链接图按深度限制、页面上限、过滤规则和评分机制进行遍历。一次 BFS 深爬顺着我 fixture 首页的链接图走了一遍,拉取了 5 个页面。这里正是宣传和实际开始分道扬镳的地方,下面我会展开说。
安装:没人会在 README 开头写出来的那一段

我这台机器上的安装体验,一方面比预期顺利,另一方面又比想象中更重。pip install -U crawl4ai 加上冒烟测试,在 Python 3.14.2 的 macOS arm64 上都成功了。PyPI 上的 >=3.10 约束本来就包含 3.14;这个结果只能证明我测试过的安装和流程可用,不能说明更广泛的兼容性。
真正的摩擦来自设置步骤。crawl4ai-setup 会为 Playwright 和 Patchright 两套环境下载浏览器资源——包括 Chrome for Testing、FFmpeg、以及 Headless Shell。如果你用的是磁盘紧张、或者网络按流量计费的笔记本,这就是实打实的成本;但文档只是顺带提了一句,并没有放在最前面。随后 crawl4ai-doctor 通过并在 14.65 秒 内抓取了 crawl4ai.com,这当然是个不错的端到端冒烟测试,但不能算任何正式基准——这个数字本身不要解读出性能优劣。
如果你要自己评估,安装部分的结论就是:要把浏览器下载成本算进去,而不只是 pip install。这更像是在搭一个无头浏览器环境,而不是往脚本里塞一个库。真正抓一条网页之前,磁盘里就已经落下了两套浏览器组件,而这是一笔无论你的业务最后用不用 Patchright 的隐身层都要支付的一次性成本。
上手实测:哪些地方稳,哪些地方需要留心
下面四个结果值得单独记下来,因为它们正好暴露了营销页常常会抹平、或者在某些情况下误标的细节。

两个公开演示页也都顺利跑通了。 在 Books to Scrape 首页上,Crawl4AI 在 2.43 秒内生成了 13,476 个字符的 Markdown。公开的 Quotes JS 页面则在约 3.1 秒内返回了 1,666 个渲染后的 Markdown 字符。这两个结果都不能证明它在大规模、对抗性网站、长时间稳定运行、会话管理、代理、重试或内存表现上的能力。
文章页暴露了 Markdown 质量上的一个注意点。 Crawl4AI 抓到了标题和全部 3/3 个正文段落,这一点很好。但原始 Markdown 也保留了导航文本、相关文章链接、订阅提示和页脚内容。这不是 bug;如果没有内容过滤器或目标选择器,“把这个页面转成 Markdown”从字面上说就是整页都转。这里的关键是要区分“原始 Markdown 转换”和“干净的文章抽取”。如果你想要后者,就需要像 PruningContentFilter 这样的内容过滤器,或者一个目标选择器——不过我还没有对它做压力测试,所以不会给它一个“干净度”分数。

那个故障页面给出的信息最有价值。 我专门返回了一个带很小正文的 HTTP 500。Crawl4AI 的结果是 success=false 且状态码 500——这一点是对的——但错误信息却写成了 “Blocked by anti-bot protection: Structural: minimal_text on small page.” 实际上根本没有反爬墙;那只是一个很小的错误页。Crawl4AI 的结构性启发式看到可见文本很少,就直接往反爬方向解释了。对于要基于它做二次开发的人来说,这点很重要:不要把“anti-bot”标签当真。先看状态码,再看实际响应内容,再判断到底是不是站点在拦你。原始结果放在基准仓库的 results/local_failure_500.json 里。
深度爬取需要你主动配置。 直接对动态页面设置 wait_for 可以顺利完成,而 BFS 深爬虽然找到了动态目录页,却返回了失败。minimal_text 的分类结果和“在卡片渲染出来之前就已经读取页面”这个推断是吻合的,但深爬并没有沿用直接抓取时的等待条件。五个页面里,3 个成功,2 个失败。由于这里并没有展示带等待条件的重跑,所以这个判断仍然只是推断,而不是被完全证明的原因。
数字最后落在哪

| 测试 | 结果 | 观察到的总耗时(单次记录) |
|---|---|---|
快速开始(example.com) | 成功,200 | 1.81 秒 |
| 本地静态目录页(Markdown) | 6/6 商品召回 | 0.731 秒 |
| 本地静态 CSS schema 提取 | 6 条 JSON 记录 | 0.740 秒 |
本地动态目录页(wait_for) | 8/8 商品召回 | 1.559 秒 |
| 本地动态 CSS schema 提取 | 8 条 JSON 记录 | 1.561 秒 |
| 文章页 Markdown | 3/3 段落(+ 模板内容) | 0.752 秒 |
| 公开 Books to Scrape 首页 | 13,476 个 Markdown 字符 | 2.425 秒 |
| 公开 Quotes JS 页面 | 1,666 个 Markdown 字符,已渲染 | 3.111 秒 |
arun_many()(6 个本地页面) | 6/6 召回 | 3.760 秒 |
| 本地 BFS 深度爬取 | 找到 5 个页面,3 成功 / 2 失败 | 3.239 秒 |
| 故意返回 500 的页面 | 失败,500(被误标为“anti-bot”) | 0.745 秒 |
这些只是冒烟测试的耗时,不是性能基准:文章并没有说明硬件、重复次数、冷启动还是热启动、缓存状态、并发控制,也没有给出波动范围。它们只能说明这些工作流在这台机器上确实跑通了。完整运行产物都放在基准仓库目录里。
如果要做足以支持决策的性能测试,应该在全新和复用的浏览器会话中重复每个工作流,报告分布而不是只给一个小数点的单次值,锁定浏览器版本,并记录 CPU、内存、缓存状态和并发设置。这样才能把库本身的开销和浏览器启动、网络波动区分开来。
| 需求 | 本次评测中的匹配度 | 主要条件 |
|---|---|---|
| 渲染页面并返回 Markdown | 适合 | 需要先过滤模板噪音,才能当作文章级输出使用 |
| 提取结构化 JSON | 适合 | 但 CSS schema 仍然需要你自己编写和维护 |
| 等待异步页面内容 | 支持 | 需要你显式定义、且针对目标页面的 wait_for 条件 |
| 深度爬取动态页面 | 有条件适用 | 必须把就绪规则一路传递下去;本次测试的默认行为会出现部分失败 |
| 作为轻量、低依赖的 HTTP 解析器使用 | 不适合 | 浏览器资源及其维护本身就是部署的一部分 |
| 使用自我修复选择器 | 本测试不支持 | 不要从其他对比文案里推断出这一点 |
优缺点
优点:
- 一个库同时支持原始 Markdown 和基于 CSS schema 的结构化 JSON,不需要把两个工具硬拼起来。
- 浏览器渲染能力内置;对于异步渲染目标,可能需要显式
wait_for。 - 本次测试中的单页工作流都在上面记录的时间内完成了;这里不做跨工具速度比较。
- Apache-2.0 许可,商业使用更友好,没有 copyleft 方面的意外。
- 项目活跃,近期有新版本,也有规模不小、参与度高的社区。
缺点:
- 首次安装很重(两套浏览器栈),但介绍里说得太轻。
- 原始 Markdown 会带上模板内容,除非你额外配置内容过滤。
- 深度爬取不会自动等待动态页面——你得每次自己配,不然就会失败。
- 失败信息有时会把普通错误标成“anti-bot”,日志里看起来会很迷惑。
- 没有自适应选择器,尽管某些对比文章会这么暗示——schema 都是手写且静态的。
- 你要自己运行并维护浏览器环境,包括更新和潜在故障。
适合谁,不适合谁
如果你是要构建 RAG 或智能体流水线的开发者,愿意运行无头浏览器环境,并且希望同一次抓取里同时拿到 Markdown 和结构化 JSON,那么 Crawl4AI 值得评估。此次测试没有覆盖对抗性站点的稳定性、长时间运行、内存、会话、重试、代理或生产部署,所以这里的结论只适用于本文测试过的工作流。
如果你想要的是一个轻量、低依赖的 HTTP 解析器,那就别选它——它恰恰相反;如果你无法为浏览器下载腾出磁盘和带宽,也不想在生产环境里自己承担浏览器栈的维护成本,也建议跳过。尤其是如果你是冲着自我修复选择器来的,那更应该直接避开:这不是这个工具的能力,围绕一个它根本没有的特性来搭流程,后面一定会踩坑。若你的目标只是干净的文章正文抽取、并去掉模板噪音,那么一个更轻量、专门做这件事的工具可能更适合你。
替代方案,以及 Thunderbit 的位置
更诚实的说法是:Crawl4AI 是一个免费、开源、需要你自行托管和维护的库。你得到的是完全控制权和没有厂商使用费,但依然要承担算力、带宽、存储、浏览器更新、schema 维护以及运维工作。
另一边则是像 Thunderbit 这样的托管抓取服务,抓取和提取都封装在 API 后面。这次没有把 Thunderbit 跑进这些 fixture 里,所以本文不会对渲染、反爬处理、验证码、准确率或速度做对标式结论。更相关的比较其实是运维责任:你是自己托管这个浏览器驱动库,还是付费让服务商帮你运维那一层。
差别在于谁来运行浏览器。用 Crawl4AI,你要自己负责渲染、等待条件、schema 和维护;用托管 API,你按调用付费,并把一部分运维责任交给服务商。这次实验没有比较这两条路径的实际结果。
相关文章基准评测:完整开源爬虫对比、Firecrawl 自托管评测、以及 trafilatura 文章抽取评测。
结论
如果你想要一个开源、基于浏览器的数据提取工具,既能输出 Markdown 又能输出结构化 JSON,而且你也愿意自己负责浏览器环境,那么 Crawl4AI 算是一个合理的选择。在这些 fixture 中,直接抓静态页和带等待条件的动态页都成功了。Apache-2.0 许可也比较宽松,不过常规的依赖和分发审查依然少不了。
记得把浏览器资源的成本算进去。原始 Markdown 在作为文章内容之前需要先过滤。深度爬取的等待条件需要你主动配置;日志里如果出现“anti-bot”,应先核对状态码和响应内容。schema 选择器仍然要你自己写、自己维护。以上就是本次测试得出的决策边界;生产规模和对抗性站点的行为,仍然还有待验证。
试用 Thunderbit 进行网页数据提取 Get Started Free
常见问题
Crawl4AI 有自适应或自我修复选择器吗? 没有。尽管有些对比文章把“adaptive intelligence”归给它,Crawl4AI 实际上只是匹配你写的 CSS/XPath schema,并不会识别元素特征,也不会在页面结构变化后重新定位元素。在测试里,结构化提取是用我手工定义的 schema 做到了 6/6 和 8/8 召回。如果站点改了 class,你的 schema 也会失效,直到你手动更新。自我修复式元素追踪是别的库的功能,不是它的。
为什么安装包这么大?
crawl4ai-setup 会为 Playwright 和 Patchright 两套环境下载完整浏览器资源——包括 Chrome for Testing、FFmpeg 和 Headless Shell。这就是把真实浏览器渲染能力带出来的代价。你需要预留磁盘和带宽;它比纯 HTTP 解析器重得多,而且即使你的工作负载根本用不到隐身层,也一样要付这笔成本。
Crawl4AI 能处理 JavaScript 渲染页面吗?
可以,因为它驱动的是真实无头浏览器。测试中,一个设置了 wait_for="css:.product-card" 的动态目录页拿到了完整的 8/8 商品召回,公开的 Quotes JS 页面也能正常渲染。需要注意的是,深度爬取不会自动把这个等待条件应用到新发现的页面上——一次 BFS 深爬在它发现的动态页面上失败了,因为它没有等待。等待条件必须由你按每次抓取单独配置。
Crawl4AI 返回的是干净的文章正文,还是整页内容?
默认是整页。测试中它抓到了所有正文段落,但也保留了导航、相关文章和页脚文本。如果你想要干净的文章抽取,需要使用内容过滤器(例如 PruningContentFilter)或目标选择器,而不是直接依赖原始 Markdown。
我能相信 Crawl4AI 的错误信息吗? 最好带着一点怀疑来看。一个故意返回 500、且正文很小的错误页,仅仅因为可见文本太少,就被标成了“Blocked by anti-bot protection”——实际上并没有反爬墙。其原始结果已经放在基准仓库里。在得出“站点在拦我”之前,一定先看真实的 HTTP 状态码和响应正文。


