网页 34,873 字符的 HTML 去掉噪音只剩 15,371 字符:Firecrawl 一套 compose 自建抓取服务,把整站变成模型能读的 Markdown

本页目录 10 节
先说一个几乎每个做 RAG 或做 Agent 的人都撞过的墙。
你要让模型读一篇文章。抓下来一看,HTML 有 8 万字符:导航栏、页脚、推荐位、Cookie 提示、内联的样式表、一串 <script>、还有一段「相关阅读」。真正的正文大概 3 千字,埋在第 4 万字符往后。
直接把这 8 万字符喂给模型,只有两个结果:要么贵得离谱,要么它开始答非所问。于是你写正则、写 XPath、按 class 名猜正文——然后下个月那个站改版了。
这篇要说的 Firecrawl,做的就是把这一步变成一次 API 调用:给一个 URL,回来的是 Markdown 或者按 schema 抽好的 JSON,不是 HTML。它开源、能自建,这一点比它多快更重要——因为抓下来的网页内容,很多时候你不想让它经过别人的服务器。
一、它到底是什么
一句话:一个「网页 → 模型可直接消费的数据」的转换层。不是爬虫框架,不是浏览器自动化库,是夹在网页和模型中间的那一层。
| 项目 | 情况 |
|---|---|
| 开源方 | Firecrawl(仓库 firecrawl/firecrawl,6,735 次提交) |
| 许可 | 主项目 AGPL-3.0;SDK 与部分 UI 为 MIT |
| 主要端点 | scrape 单页 / crawl 整站 / map 列全站 URL / search 搜索并取全文 |
| 其他端点 | parse(PDF、DOCX 转 Markdown)/ batch scrape / monitor(内容变更通知)/ agent(描述需求自动采集)/ interact(与页面交互) |
| 输出格式 | Markdown(主推)、HTML、截图、结构化 JSON(可带 schema) |
| SDK | Python / Node / Go / Java / Elixir / Rust / Ruby / .NET / PHP 共 9 种 |
| 其他入口 | 命令行 firecrawl-cli、MCP 服务器 firecrawl-mcp |
| 自建 | docker compose,默认接口 http://localhost:3002 |
| 费用 | 自建免费(自己出机器);云服务免费档每月 1,000 credits,付费 $19/月起 |
有一点得先讲清楚,因为它决定了你该用哪条路:「开源版」和「云服务」不是同一套能力。官方文档专门有一张表列这个差异,而这个差异恰好是本文第四节的重点。
二、自建:从零到第一个成功的 scrape
官方自建文档把版本钉死在 v2.11.162,并且提醒「换版本要重新看它的 compose 契约」。这行提醒是有意义的——照抄旧教程的 compose 参数,在新版本上很可能起不来。
前置只有四样:Git、Docker Engine 或 Docker Desktop、Compose v2、curl;再确认 3002 端口空着。
然后是最小可用的四行环境变量:
USE_DB_AUTHENTICATION=false POSTGRES_USER=postgres POSTGRES_PASSWORD=(至少 32 位随机) POSTGRES_DB=postgres
这里有个容易踩的点:数据库名必须保持 postgres,因为 v2.11.162 自带的 pg_cron 配置指向这个名字。改成自己的库名,初始化会失败。
接着三步:
git clone仓库,git checkout v2.11.162;docker compose up --build -d(第一次要构建镜像,慢是正常的);curl http://localhost:3002/v0/health/readiness,期望返回{"status":"ok"}。
但官方特意强调:这个 ok 只说明 API 进程活着。它不检查 Redis、PostgreSQL、RabbitMQ、Playwright 和 worker,也不检查能不能访问外网。真正的验收是发一次 scrape:
POST /v2/scrape,body 里写 {"url": "...", "formats": ["markdown"], "timeout": 60000},看到 success: true 和一段 markdown,才算这套东西在你机器上通了。
整套栈不止一个容器:API、worker、Playwright 渲染服务、Redis、PostgreSQL(默认队列 NuQ),还可能出现 RabbitMQ。这也是它没法塞进一台很弱的机器的原因——官方很诚实地写着「不发布经过验证的最低主机规格」,等于说「自己看着办」。
三、自建之后,什么能用、什么用不了
这是全文最该抄下来的一张表,因为绝大多数「自建 Firecrawl 踩坑」都栽在这里:
| 你想要 | 自建默认栈 |
|---|---|
| scrape / crawl / map / search 四个核心端点 | 能用,Fetch 与 Playwright 都已包含 |
| Markdown、HTML 输出 | 能用 |
| 结构化 JSON / LLM 抽取 | 要自己接一个 OpenAI 兼容服务或本地 Ollama,否则用不了 |
| 截图 | 默认栈不支持,要 Fire-engine |
| 页面点击、填表等动作 | 默认栈不支持,要 Fire-engine |
| interact / agent / browser / 反馈 | 走云服务 |
| 音频、视频、菜单等专用格式 | 走云服务 |
换句话说:自建拿到的是「抓取 + 转 Markdown + 整站遍历 + 搜索」这四件最常用的事,拿不到的是「会点会填会截图」那部分。
如果你的用途是「把文档站、博客、论坛抓成 Markdown 喂给模型」,自建完全够,而且一分钱不花。如果你的用途是「登录后翻页、抓取需要点开的列表」,那自建的默认栈干不了,得用云。
四、钱:免费额度能干什么,自建到底省多少
云服务的计费单位是 credit,规则不复杂但有几处容易忽略:
| 动作 | 消耗 |
|---|---|
| 抓一页(scrape / crawl / map,基础 Markdown) | 1 credit |
| 搜索(一次查询最多 10 条结果) | 2 credits |
| 加 JSON / Question / Highlight 格式 | 每页 +4 |
| interact 浏览器会话 | 2 credits/分钟(带自然语言提示词 7/分钟) |
| monitor 变更监控 | 1 credit/页/次检查 |
| agent | 每天 5 次免费 |
免费档每月 1,000 credits——按基础抓取算是 1,000 页,平均一天 33 页。但如果你每页都要结构化 JSON,一页就是 5 credits,免费额度立刻缩水到 200 页。
付费档里最便宜的 Hobby 是 $19/月 5,000 credits(年付折到 $16),折算下来一页基础抓取不到 3 分钱人民币。这个价格其实不贵,贵的是「页数一上去、还要加 JSON 格式」的时候——5 credits 一页的话,5,000 credits 只够 1,000 页。
| 方案 | 月费 | credits/月 | 纯基础抓取的页数 |
|---|---|---|---|
| Free | $0 | 1,000 | 1,000 |
| Hobby | $19(年付约 $16) | 5,000 | 5,000 |
| Standard | $99 | 100,000 | 100,000 |
| Growth | $399 | 500,000 | 500,000 |
| Scale | $749(年付约 $599) | 1,000,000 | 1,000,000 |
还有一条藏在定价页脚注里的规则值得知道:抓取失败、返回空结果不计费;但 403、404 这种「页面明明给了回应」的情况,照样收 1 credit。批量抓一个含大量失效链接的老站时,这笔钱会悄悄多花。
那自建是不是一定更省?不一定。账要这么算:一台能同时扛起 Chromium、PostgreSQL、Redis 和 worker 的机器,云主机月费通常不低于 Hobby 档;再加上你自己要负责升级、备份、监控、被爬站封 IP 之后的换代理。所以:
- 每月几千页以内——用云,免费额度或 Hobby 就够,别折腾;
- 要抓的内容敏感、不能出内网——自建,这时候省的不是钱是合规;
- 量大且要改代码——自建,AGPL 允许你改,改完自己跑不用开源(对外提供服务才需要)。
五、它凭什么减少「喂给模型的字数」
官方博客里有一个对比,同一页(Hacker News 首页),两个工具各抓一次:
| 返回内容 | 耗时 | |
|---|---|---|
| 对手(ScrapingBee) | 34,873 字符原始 HTML | 2.85 秒 |
| Firecrawl | 15,371 字符干净 Markdown | 1.16 秒 |
字符少了约 55%,速度约 2.5 倍,而且标题已经被解析进 metadata 里了。
这 55% 不是压缩,是删除。删掉的是标签、脚本、样式、导航和页脚——也就是模型本来就不该读的那部分。对于按 token 计费的场景,这个比例直接等于账单的比例。
要结构化数据的话,可以带 schema,直接拿到 JSON,中间不经过「先给 HTML 再让模型解析」这一道:
传一个描述目标结构的 schema(比如「取前十条标题和分数」),返回的就是填好的 JSON 数组。这一步省的不只是 token,还有一次模型调用的不确定性和延迟。
六、接进 Agent 的三条路
它没把自己做成一个封闭的 SaaS,接入方式铺得很宽:
- SDK:9 种语言,Python 是
pip install firecrawl,Node 是npm install firecrawl; - CLI:
firecrawl-cli,适合写进脚本或 CI; - MCP:
firecrawl-mcp,接进 Claude Code、Cursor 这类支持 MCP 的客户端,让它自己决定抓哪个页面。
还有一个对评测很友好的设计:核心端点可以不带 Key 直接调。search、scrape、parse、crawl、map、agent 都支持这种「先试再注册」的方式,官方甚至给了每月 1,000 的免费额度。这意味着你可以先拿自己最难抓的那个 URL 试一次,通不通再谈接入——而不是先注册、先绑卡、再发现抓不下来。
七、合规与安全:两件必须自己做对的事
第一件是抓什么。官方 README 写得很清楚:默认遵守 robots.txt,抓取时必须遵守目标站点的条款与隐私政策,责任在使用者。这不是免责声明式的废话——它决定了你抓的站是「公开文档」还是「别人的付费内容」,这两件事性质完全不同。
第二件是别把自己建的这套裸露在网上。自建文档的快速上手流程里,USE_DB_AUTHENTICATION=false 意味着任何能访问 3002 端口的人都能免密钥让你去抓任意 URL。官方原话是「不要把这个未鉴权的基线暴露在公网」,并且默认 compose 文件不带持久化卷——容器重建,队列里的任务和数据库就没了。
它还有一个细节做得不错:Lockdown Mode。开启后 /scrape 被限制为只读缓存结果,一个被提示词注入的 URL 无法发起真实的外网请求。如果你的 Agent 会去抓「它自己从网页里读到的链接」,这个开关值得打开——否则一个恶意页面就能让你的抓取服务去访问内网地址。
八、六条冷水
- 自建默认栈没有截图和页面动作。这是最容易被「开源免费」四个字盖住的落差,官方文档写得很直白:要 Fire-engine。
- 结构化抽取要自己接模型。自建不接 OpenAI 兼容服务或 Ollama,JSON 格式就用不了——等于你只拿到了「干净的 Markdown」这一半。
- 96% 覆盖率和 P95 3.4 秒是官方口径。没有任何第三方复现,而且这两个数字显然是在它自己的基础设施上测的,不是你那台 2 核机器。
- 没有官方最低配置。「不发布经过验证的最低主机规格」这句话,翻译过来就是「跑不动别怪我们」。
- AGPL 不是随便用。自己内部跑没问题;如果你基于它改一版、再作为服务卖给别人,改动部分要开源。
- 能不能抓到,最终还是取决于目标站。反爬、登录墙、地区限制这些事,换哪个抓取工具都一样要面对。它解决的是「抓下来之后怎么变干净」,不是「怎么绕过限制」——后者也不是它承诺的。
九、谁该装,怎么开始
| 你的情况 | 建议 |
|---|---|
| 要给 RAG 灌一批文档站、博客 | 自建,scrape + crawl 就够,零成本 |
| 要让 Agent 自己上网查资料 | 先用云 + MCP,省掉运维;量大再迁自建 |
| 抓的内容敏感、不能出内网 | 自建,这是它相对云服务最大的价值 |
| 需要登录、翻页、点按钮 | 自建默认栈做不了,用云或另配浏览器自动化 |
| 每月只要几百页 | 别自建,免费额度足够,运维成本远高于省下的钱 |
上手顺序建议这样走,别一上来就 compose:
- 先去官网拿免费额度,用一个你最难抓的 URL 试一次 scrape,看返回的 Markdown 干不干净;
- 干净的话,再试一次 crawl,看它能不能把整站的目录结构走完;
- 确认能力够用,再决定是留在云上还是自建——先验证能力,再投入运维,顺序反过来最容易白折腾一晚上;
- 自建的话,照着官方 v2.11.162 的文档走,别抄博客里的旧 compose;起来之后第一件事是加鉴权、加持久化卷。
十、一句话
抓网页这件事,难的从来不是「抓」,是「抓下来之后,哪些字该给模型看」。Firecrawl 把这一步做成了一次调用,并且愿意开源——这意味着你可以把它关在自己的机房里,让网页内容不出内网。
它的诚实之处在于:自建版明确告诉你少了什么(截图、页面动作、Agent),而不是让你装完才发现。对做 RAG 和做 Agent 的人来说,一个「知道自己边界在哪」的抓取层,比一个号称什么都能干的,靠谱得多。
↓ 获取资源
点击按钮直接前往资源页面。