Firecrawl 深度调研报告:功能、实现原理、架构与自研落地建议
调研时间:2026-08-12
数据来源:GitHub 官方仓库(
firecrawl/firecrawl,main 分支实时抓取)、官方文档 docs.firecrawl.dev、源码关键文件调研方式:GitHub API + raw 直链源码分析(未 clone,仓库 174MB)
1. 项目概述
| 维度 | 数据 |
|---|---|
| 项目名 | Firecrawl 🔥 |
| 定位 | The context API to search, scrape, and interact with the web at scale(网页上下文 API:搜索、抓取、交互) |
| GitHub Stars | 165,863(截至 2026-08-12) |
| Forks | 9,321 |
| 主语言 | TypeScript |
| 许可证 | AGPL-3.0(SDK 为 MIT) |
| 创建时间 | 2024-04-15 |
| 最近提交 | 2026-08-11(活跃度极高,几乎每日提交) |
| 仓库大小 | 174 MB(monorepo) |
| 商业模式 | 开源核心 + 云 SaaS(firecrawl.dev),云版有额外功能 |
一句话定位 :把"网页抓取"从工程问题变成"一次 API 调用"。用户不需要关心代理轮换、JS 渲染、反爬绕过、Markdown 清洗------Firecrawl 声称覆盖 96% 的网页 ,P95 延迟 3.4 秒(百万级页面实测)。
发展脉络(从代码仓库可清晰看出):
- v0/v1:纯 Scrape → Crawl → Extract 三件套(提取网页为 Markdown)
- v2(2025 下半年):升级为 Search + Scrape + Interact + Agent 四大核心 + Batch/Crawl/Map,引入自研 Fire-engine 浏览器渲染引擎
- 2026:加入 Spark 模型(自研 LLM)、Research(学术搜索)、Ask(文档问答)、Browser API(持久浏览器会话)、Deep Research 等企业能力
2. 功能全景清单
2.1 四大核心端点(v2)
| 端点 | 功能 | 关键参数/能力 |
|---|---|---|
/v2/scrape |
单 URL 抓取,转 Markdown/HTML/截图/JSON | formats: markdown/html/screenshot/json/rawHtml;actions(点击/滚动/输入/等待/按键);waitFor(等待选择器/网络空闲);mobile(移动端模拟);geolocation(地理位置);skipTlsVerification;proxy: basic/stealth |
/v2/search |
搜索引擎结果 + 自动抓取全文 | 底层接 SearXNG 等元搜索;返回 url/title/markdown;支持 location、country、limit、lang、scrapeOptions |
/v2/interact |
在已抓取页面上用 自然语言提示词 交互 | POST /v2/scrape/{scrapeId}/interact,prompt 如 "Search for mechanical keyboard" → 返回 output + liveViewUrl(实时视频画面);底层是自研浏览器 Agent(lib/scrape-interact/browser-agent.ts) |
/v2/agent |
自主数据收集:描述需求,AI 自动搜索/导航/抓取 | prompt(无 URL 也可);可选 schema(结构化输出,pydantic/zod);可选 urls(聚焦指定页面);model: spark-1-mini(默认,便宜 60%)/ spark-1-pro。是 /extract 的进化版,不需要预先知道 URL |
2.2 批量与站点级端点
| 端点 | 功能 | 说明 |
|---|---|---|
/v2/crawl |
全站爬取(异步任务) | limit、maxDepth、includePaths/excludePaths(正则)、ignoreSitemap、allowSubdomains;返回 jobId,GET /v2/crawl/{id} 轮询;WebSocket 实时进度;可 cancel |
/v2/map |
站点 URL 发现 | 优先读 sitemap.xml,再回退爬取页面提取链接;search 参数按相关性排序(map-cosine.ts 余弦相似度);limit、ignoreSitemap |
/v2/batch/scrape |
一次抓取上千 URL | 异步任务,formats 统一或按 URL 指定;webhook 通知 |
/v2/parse |
文档解析(无浏览器) | 直接从 HTTP 拉取 PDF/DOCX/XLSX/PPTX/RTF/ODT 等,用 Go 库解析为 Markdown;parseApi.ts |
/v2/browser |
持久浏览器会话管理 | create/execute/delete/list;session 内保持登录态、cookies;可执行 JS、截图、导航(scrape-browser.ts) |
2.3 监控与研究类端点(企业级)
| 端点 | 功能 | 说明 |
|---|---|---|
Monitor (/v2/monitor) |
网页变化监控 | create/update/run/delete;按 schedule 抓取对比,变化时发通知;分 Page(页面)/ Website(全站)/ Web-scale(全网)三档 |
Research (/v2/research) |
学术论文搜索/获取 | research-paper、research-search-papers、research-related-papers;学术类垂直搜索 |
/v2/ask |
文档问答 | 对抓取内容做 RAG 问答(features/ask) |
| Change Tracking | 页面 diff | transformers/diff.ts,两个时间点的 Markdown diff |
2.4 支撑性能力
| 能力 | 说明 |
|---|---|
| Actions | 抓取前执行浏览器动作序列:click、scroll、type、wait、press、screenshot、getCookies、executeJavascript、file(下载)、pdf |
| LLM 结构化提取 | /v2/scrape 里 json format + schema;或 extract 端点:从 URL 列表/搜索词中提取结构化数据(lib/extract/) |
| Screenshot | 视口截图 + 全页截图(screenshot@fullScreen) |
| PDF 引擎 | 专门处理 PDF:提取文本、OCR(engines/pdf/)、页面级 Markdown |
| 文档转换 | DOCX/XLSX/PPTX/RTF/ODT → Markdown/HTML(engines/document/) |
| PII 脱敏 | transformers/redactPII.ts,从抓取结果中删除姓名/邮箱/电话等 |
| Branding | 品牌元素检测:logo、品牌色、声明式 logo 校验(lib/branding/) |
| 锁定模式 Lockdown | 只允许从白名单域名抓取(企业安全) |
| Keyless 免密 | 无需 API key 的免费额度(按 IP 限流,lib/keyless.ts) |
| 威胁防护 | Google Web Risk 域名风险检查 + PII 过滤(lib/threat-protection/) |
| Zero Data Retention (ZDR) | 完成后立即清除中间数据(合规) |
| Webhooks | 异步任务完成通知;支持自托管 webhook |
2.5 集成生态
- 8 种官方 SDK :Python(
firecrawl-py)、Node.js、Go、Java、Rust、Ruby、.NET、PHP、Elixir - MCP Server :
firecrawl-mcp,一行配置接入任意 MCP 客户端 - CLI + Agent Skills :
firecrawlCLI、firecrawl-skills(Claude Code/Codex/OpenCode 等直接可用) - Workflows :
firecrawl-workflows(可复用的抓取工作流) - Agent Onboarding:AI Agent 可通过 SKILL.md 引导用户注册拿 key
- 平台集成:Zapier、n8n、Lovable、LangChain、CrewAI、Dify、Flowise 等 17+ 集成
2.6 开放与云版差异
开源版(自托管)包含核心 Scrape/Crawl/Map/Batch/Search/Extract;云版额外提供:Fire-engine 高级反爬、Agent/Interact/Ask、Research、监控、品牌等企业功能。README 明确说明开源核心为 AGPL-3.0。
3. 核心实现原理
3.1 抓取引擎瀑布流(Scrape 的核心机制)⭐
源码:apps/api/src/scraper/scrapeURL/engines/index.ts
设计思想 :不依赖单一抓取方式,而是维护一个多引擎按质量排序的候选列表,用"瀑布流"(waterfall)并发调度,先到先得,失败自动降级到下一个引擎。
引擎清单与质量分
| 引擎 | quality | 适用场景 |
|---|---|---|
exchange |
2000 | 交换站/缓存交换(最新引入) |
index |
1000 | 索引缓存命中(services/index.ts,Redis/Postgres 缓存,总是最先尝试) |
fire-engine;chrome-cdp |
50 | 自研全功能浏览器引擎(JS 渲染、actions、截图) |
fire-engine(retry);chrome-cdp |
45 | 同上,带重试 |
playwright |
20 | 轻量 Playwright 引擎 |
fire-engine;tlsclient |
10 | TLS 指纹 HTTP 客户端(轻量反检测) |
fetch |
5 | 纯 HTTP GET 兜底(undici) |
pdf / document |
-20 | 专用解析器(非 HTML 内容,负分 = 仅特殊场景使用) |
调度算法
1. 根据请求格式生成 Feature Flags(actions/screenshot/pdf/mobile/waitFor/...)
2. 计算每个引擎的 supportScore = Σ(支持的 flag × flag 权重)
3. 筛选 supportScore >= totalPriority/2 的引擎;若存在 quality>0 引擎则剔除 quality<0 的
4. 按 supportScore↓ → quality↓ 排序
5. 主循环:
a. 取出下一个引擎并发启动 scrape
b. Promise.race([所有活跃引擎, 瀑布流超时器, 整体超时器])
c. 某引擎成功(内容非空 + 状态码 2xx/304 + 无页面错误)→ 返回
d. 失败 → 移除该引擎,继续
e. 瀑布流超时(引擎太慢)→ 启动下一个引擎(多引擎并行竞争)
6. 全部失败 → NoEnginesLeftError
质量评估三要素
typescript
const isLongEnough = markdown.trim().length > 0; // 内容非空
const isGoodStatusCode = 200-299 || 304; // 状态码正常
const hasNoPageError = engineResult.error === undefined; // 无页面错误
关键细节 :401/403/429 + proxy="auto" → 自动添加 stealthProxy flag 重试(反爬自动升级)。AbortManager 管理三级超时(Scrape 整体 / 引擎 / URL)。
这正是多引擎抓取架构的经典设计,本次调研从源码实时确认。
3.2 HTML → Markdown 转换(Go 微服务)
源码:apps/api/sharedLibs/go-html-to-md/html-to-markdown.go + lib/html-to-markdown-client.ts
为什么用 Go :源码注释明确说明------"避免阻塞 Node.js 事件循环"。HTML→Markdown 是 CPU 密集转换,用 Go 编译为 C 共享库(-buildmode=c-shared)通过 N-API 调用,或独立 HTTP 微服务。
go
converter := md.NewConverter("", true, nil)
converter.Use(plugin.GitHubFlavored()) // GFM:表格、任务列表、删除线
converter.Use(plugin.RobustCodeBlock()) // 代码块保护
markdown, err := converter.ConvertString(html)
基于 github.com/firecrawl/html-to-markdown(Go 版 turndown 风格转换器)。
3.3 Transformers 管线(文档后处理链)
源码:apps/api/src/scraper/scrapeURL/transformers/index.ts
抓到的原始内容不是直接返回,而是经过一条有序的 transformer 管线:
engine 原始结果
→ rawHtml (原始 HTML)
→ html (htmlTransform:移除 script/style/nav/footer 等噪声元素)
→ markdown (Go 服务转换,按需)
→ metadata (title/description/og 标签/sourceURL)
→ links (extractLinks:解析 <a href>)
→ images (extractImages:提取图片 URL)
→ 各 format 分支:
├─ json → deterministicJson(CSS/XPath schema 提取)或 LLM extract
├─ summary → LLM 摘要
├─ query → LLM 问答
├─ agent → Agent 交互
├─ attributes → 属性提取
├─ product/menu → 电商/菜单专用 schema
├─ audio/video → 音视频信息提取
├─ redactPII → 脱敏
├─ diff → 变化追踪
└─ sendToSearchIndex → 索引
设计要点 :每个 transformer 依赖前序输出(requireRawHtml() / 检查 document.html === undefined 报错),形成严格的 DAG,保证顺序正确性。
3.4 LLM 结构化提取(Extract/Agent 核心)
源码:apps/api/src/scraper/scrapeURL/transformers/llmExtract.ts、lib/extract/(含 fire-0 新一代)
流程:
抓取 URLs → 合并 Markdown → trimToTokenLimit() 截断
→ 选择模型 → generateObject({ schema, prompt, system })(Vercel AI SDK)
→ 校验/修正 → 计费 → 返回 { data, sources, llmUsage }
模型选择(智能):
typescript
selectModelForSchema(schema):
无 schema → gpt-4o-mini
含 $ref/$defs/definitions(递归 schema)→ gpt-4.1(更强)
简单 schema → gpt-4o-mini(省钱)
Schema 规范化 normalizeSchema():
type: object→ 全部字段 required、additionalProperties: false- 递归处理
$defs/anyOf/oneOf/allOf
Token 截断(防事件循环阻塞 + 精确控制):
1. maxTokens × 5 chars 字符级预截断(快速,防阻塞)
2. tiktoken encoding_for_model() 精确计数
3. tokens.slice(0, maxTokens) → decode 回文本
4. 兜底:charsPerToken=2.8 估算
失败重试 :配额超限/速率限制 → 自动降级到 retryModel(gpt-4.1-mini)。LLM 拒绝提取(版权/内容政策)→ 抛 LLMRefusalError。
Agent(fire-0 新一代提取) :lib/extract/fire-0/ 使用独立完成管线 completions/,支持自研 Spark 模型(spark-1-mini / spark-1-pro),有 reranker(重排序)和 URL 处理器。
3.5 Fire-engine:自研浏览器渲染引擎(云版核心壁垒)
源码:apps/api/src/scraper/scrapeURL/engines/fire-engine/
Fire-engine 是 Firecrawl 自研的托管浏览器集群(不在开源仓库内,通过 HTTP API 调用):
| 引擎类型 | 用途 |
|---|---|
chrome-cdp |
完整 Chrome DevTools Protocol 浏览器:执行 actions、截图、移动模拟、地理定位、持久存储 |
tlsclient |
轻量 TLS 指纹 HTTP 客户端:无头请求 + 反检测(模仿真实浏览器 TLS 指纹) |
请求字段 (scrape.ts 的 FireEngineScrapeRequestChromeCDP):engine、actions[]、blockMedia、mobile、geolocation、timeout、maxAge、zeroDataRetention、persistentStorage.uniqueId(会话保持)。
响应 :content(HTML)、pageStatusCode、screenshots[]、actionResults[](每个 action 的截图/抓取结果)、file(下载文件)、docUrl(GCS 暂存)、youtubeTranscriptContent(YouTube 字幕)。
反爬自动升级 :fire-engine 失败且返回 retryWithStealth: true → API 层自动改用 stealth 代理重试。
3.6 Engpicker:AI 驱动的引擎选择器(2026 新架构)
源码:apps/api/src/lib/engpicker.ts + Rust native(@mendable/firecrawl-rs)
问题 :不同网站对抓取方式的偏好不同(有的静态、有的 JS、有的强反爬)。Engpicker 为每个域名学习最优引擎:
1. 对未知域名:尝试各引擎抓取(basic/stealth 代理)
2. 用 GPT-4o-mini 评估抓取质量("这个 markdown 是否成功抓取了内容")
3. 计算 verdict(Rust 侧 computeEngpickerVerdict)
4. 按 domain_level(域名层级)缓存结论到 PostgreSQL(engpicker_jobs 表)
5. 后续同域名请求直接命中推荐引擎
这解释了 Firecrawl "越用越准" 的特性------按域名积累抓取经验。
3.7 Index 索引缓存(为什么"快")
源码:apps/api/src/services/index.ts、services/indexing/
index 引擎 quality=1000 总被最先尝试。它维护了一个网页内容索引缓存(Redis/PostgreSQL 双后端):
- 同一 URL 再次请求 → 直接命中缓存(
maxAge控制新鲜度) - 支持
useIndex/useSearchIndex两级 - 索引 worker(
index-worker.ts)后台持续构建 - Engpicker 与 index 配合:缓存不命中才走引擎瀑布流
3.8 Crawl 编排(多页爬取)
源码:apps/api/src/scraper/crawler/、lib/crawl-redis.ts、services/queue-*
状态存储(Redis):
| 键 | 用途 |
|---|---|
crawl:{id} |
任务元数据 JSON |
crawl:{id}:url:{hash} |
URL 去重锁(NX,24h TTL) |
crawl:{id}:jobs |
已入队集合 |
crawl:{id}:jobs_done |
已完成集合 |
crawl:{id}:robots_blocked |
被 robots.txt 阻止的 URL |
工作器循环:
processJobInternal(job):
1. scrapeURL() → Document
2. extractLinksFromHTML(html) → <a href> 列表
3. filterLinks(links, maxDepth) → 12 种过滤链:
URL 解析 → 非 web 协议 → #锚点 → 深度检查 → excludes 正则
→ includes 正则 → 外部域名 → 子域名 → 反向爬取检查
→ 社交媒体 → 文件类型 → robots.txt
4. checkUrlsAgainstThreatPolicy() → 威胁过滤
5. 对每个通过链接: lockURL()(去重)→ 入队
6. 计费 + 日志 + Webhook
队列双后端(NuQ) :默认 PostgreSQL(apps/nuq-postgres,带 pg_cron),可选 FoundationDB (NUQ_BACKEND=fdb,实验性,更适合超大规模)。RabbitMQ 做任务分发。
3.9 搜索实现
源码:apps/api/src/search/、lib/search-query-builder.ts
- 自托管用 SearXNG(开源元搜索)聚合多个引擎
- 云版接自研/商业搜索索引(
search-index-client.ts) - 结果自动送 scrape 管线抓全文 → 返回
markdown search-query-builder.ts负责把查询改写适配不同后端
3.10 安全与合规
- Threat Protection :Google Web Risk(域名风险查杀)+ 域名黑名单 + PII 检测(
lib/threat-protection/) - ZDR :完成后立即删除中间数据(
zdr-helpers.ts) - robots.txt :默认遵守(
lib/robots-txt.ts,shouldCheckRobots.ts按策略跳过) - Keyless 限流 :按 IP 每日配额(
lib/keyless.ts),Spur Context API 检测代理/VPN 滥用 - IP/Key 白名单 :企业可用(
lib/ip-restriction.ts、key-restriction.ts)
4. 系统架构
4.1 逻辑分层
┌────────────────────────────────────────────────────────────┐
│ 客户端层 (SDK/CLI/MCP/Skills) │
│ Python · Node · Go · Java · Rust · Ruby · .NET · PHP │
└──────────────────────────┬─────────────────────────────────┘
│ HTTPS
┌──────────────────────────▼─────────────────────────────────┐
│ API 层 (Express + TypeScript) │
│ routes → controllers/v1, v2 → 校验 (zod) → 计费 → 调度 │
└──────────────────────────┬─────────────────────────────────┘
│
┌──────────────────────────▼─────────────────────────────────┐
│ 核心抓取层 (scraper/scrapeURL) │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 引擎瀑布流 (Engines Waterfall) │ │
│ │ exchange(2000) → index(1000) → fire-engine(50) │ │
│ │ → fire-engine-retry(45) → playwright(20) │ │
│ │ → tlsclient(10) → fetch(5) → pdf/doc(-20) │ │
│ └──────────────────────────────────────────────────────┘ │
│ ↓ │
│ Transformers 管线: rawHtml→html→markdown→metadata→links │
│ →images→LLM extract/summary/query/agent/redactPII/diff │
└──────────────────────────┬─────────────────────────────────┘
│
┌──────────────────────────▼─────────────────────────────────┐
│ 执行引擎集群 (独立服务/容器) │
│ Fire-engine (chrome-cdp / tlsclient) │
│ Playwright 微服务 (playwright-service-ts) │
│ Go HTML→Markdown 服务 │
│ PDF 解析 (fire-pdf/runpod) + 文档解析 (Go) │
└──────────────────────────┬─────────────────────────────────┘
│
┌──────────────────────────▼─────────────────────────────────┐
│ 基础设施层 │
│ Redis (缓存/去重/限流) · PostgreSQL (NuQ队列/Engpicker) │
│ RabbitMQ (任务分发) · FoundationDB (可选队列后端) │
│ ClickHouse (并发日志) · GCS (中间结果暂存) │
└────────────────────────────────────────────────────────────┘
4.2 monorepo 结构(apps/)
apps/
├── api/ # 主 API 服务(Express + TS,核心抓取逻辑)
│ └── src/
│ ├── controllers/ # v0/v1/v2 路由控制器
│ ├── scraper/
│ │ ├── scrapeURL/ # ⭐ 核心:引擎瀑布流 + transformers
│ │ │ ├── engines/ # exchange/index/fire-engine/playwright/fetch/pdf/document/wikipedia/x-twitter
│ │ │ ├── transformers/ # llmExtract/agent/deterministicJson/product/menu/audio/video/diff/redactPII
│ │ │ ├── postprocessors/ # youtube 等
│ │ │ └── lib/ # abortManager/extractLinks/extractMetadata/smartScrape
│ │ ├── crawler/ # sitemap 爬取
│ │ └── WebScraper/ # 旧版抓取器 + sitemap
│ ├── lib/ # engpicker/extract/deep-research/html-to-markdown/robots-txt/threat-protection/keyless/...
│ ├── services/ # index 缓存/queue 队列/webhook/billing/rate-limiter/redis
│ ├── search/ # SearXNG 搜索集成
│ ├── db/ # Drizzle ORM schema
│ ├── native/ # Rust 原生模块 (crawler/document/engpicker)
│ └── sharedLibs/ # Go 共享库 (go-html-to-md)
├── playwright-service-ts/ # Playwright 浏览器微服务
├── go-html-to-md-service/ # Go HTML→Markdown 微服务
├── nuq-postgres/ # NuQ 队列 PostgreSQL 镜像(pg_cron)
├── redis/ # Redis 配置
├── ui/ # 管理界面 (ingestion-ui, React)
├── test-site/ # 测试站点
├── test-suite/ # 评测套件 (含 load-test)
└── *-sdk/ # 8 种语言 SDK
4.3 关键设计模式
- Scrape 为一切的核心 :Crawl 每页 = scrapeURL();Extract/Agent = 多次 scrape + LLM。
scrapeURL()是所有功能的公共地基。 - 质量分驱动的引擎竞争:不 try/catch 串行,而是并发竞争 + 瀑布流超时,兼顾速度与成功率。
- Go/Rust 混合加速:HTML→Markdown 用 Go(c-shared),引擎选择计算用 Rust(WASM/native),避免阻塞 Node 事件循环。
- 索引缓存 + Engpicker 学习:同一域名第二次抓取即可命中经验缓存,这是与普通爬虫的本质差异。
- ZDR 设计:大文件(截图/PDF)存 GCS 临时桶,完成后清理,合规友好。
5. 部署架构
5.1 Docker Compose(官方自托管)
服务清单(docker-compose.yaml):
| 服务 | 镜像/构建 | 资源限制 | 用途 |
|---|---|---|---|
api |
构建 apps/api 或 ghcr.io/firecrawl/firecrawl |
4 CPU / 8G | 主 API + 全部 worker(harness 启动) |
playwright-service |
构建 apps/playwright-service-ts | 2 CPU / 4G | Playwright 浏览器微服务(MAX_CONCURRENT_PAGES) |
redis |
redis:alpine | --- | 缓存/去重/限流 |
rabbitmq |
rabbitmq:3-management | --- | 任务队列分发 |
nuq-postgres |
构建 apps/nuq-postgres | --- | NuQ 队列后端(pg_cron 调度) |
foundationdb |
foundationdb/foundationdb:7.3.63 | --- | 可选队列后端(NUQ_BACKEND=fdb) |
关键环境变量:
NUM_WORKERS_PER_QUEUE=8、CRAWL_CONCURRENT_REQUESTS=10、MAX_CONCURRENT_JOBS=5、BROWSER_POOL_SIZE=5OPENAI_API_KEY/OLLAMA_BASE_URL(LLM 提取需要,可换 OpenAI 兼容端点)SEARXNG_ENDPOINT(搜索功能)PROXY_SERVER/PROXY_USERNAME/PROXY_PASSWORD(代理池)NUQ_BACKEND=fdb切换 FoundationDB
自托管注意(SELF_HOST.md 明确警告):
- 默认 API 无认证 (
USE_DB_AUTHENTICATION=false),离开可信网络必须先加认证 + TLS - Compose 无持久卷 → 数据不保证存活,生产需自配备份
- 自托管不含 Fire-engine(云版专属)→ 反爬能力弱于云版
5.2 Kubernetes
examples/kubernetes/cluster-install/:api / worker / playwright-service / redis / nuq-postgres 的 YAMLexamples/kubernetes/firecrawl-helm/:完整 Helm chart(values.yaml + overlays dev/prod),含 RabbitMQ、cclog-worker、extract-worker、nuq-prefetch-worker 等
5.3 可观测性
- ClickHouse 并发日志(
clickhouse/concurrency_logs.sql) - Sentry、OpenTelemetry(
lib/otel-tracer.ts)、Prometheus metrics(admin/metrics) - 日志分级:winston +
LOGGING_LEVEL
6. 技术栈明细
| 层 | 技术 |
|---|---|
| 语言 | TypeScript(主)、Go(HTML→MD)、Rust(native 计算) |
| Web 框架 | Express 5(v2 测试 express5.test.ts) |
| 校验 | Zod(全部请求/响应 schema 校验) |
| ORM | Drizzle(PostgreSQL) |
| AI SDK | Vercel AI SDK(generateObject/generateText)+ tiktoken |
| LLM | OpenAI GPT 系列 + 自研 Spark 模型(云)+ 可接 Ollama/兼容端点 |
| 队列 | NuQ(PostgreSQL 默认 / FoundationDB 可选)+ RabbitMQ + Bull |
| 缓存/状态 | Redis(去重锁/限流/会话) |
| 浏览器 | 自研 Fire-engine + Playwright 微服务 |
| 反爬 | TLS 指纹客户端 + stealth 代理 + 代理轮换 |
| 存储 | PostgreSQL、Redis、GCS(临时文件)、ClickHouse(日志) |
| 部署 | Docker Compose、K8s + Helm、GitHub Actions CI/CD |
7. 自研落地建议(重点)
若要在自研项目中实现类似 Firecrawl 的能力,基于本次调研的源码级理解,可参考以下分层建议。
7.1 先想清楚:你要做哪个"级别"的 Firecrawl?
| 级别 | 对应能力 | 工作量 | 推荐 |
|---|---|---|---|
| L1 单页抓取 API | scrape → markdown/html/json | 1-2 周 | ⭐ 先做这个 |
| L2 多引擎 + 瀑布流 | 静态/JS/反爬自动降级 | +1-2 周 | ⭐ 核心差异点 |
| L3 全站爬取 | crawl + map + 去重 + 队列 | +1-2 周 | 视需求 |
| L4 LLM 提取 | extract/agent(schema 结构化) | +1-2 周 | 结合免费模型 |
| L5 企业能力 | 监控/搜索/浏览器会话/反爬集群 | 数月 | 商业化再说 |
7.2 L1:单页抓取 API(地基)
必须复刻的架构模式:Scrape → Transformers 管线分层。
输入: URL + formats + options
↓
1. 抓取层(先简单:HTTP 客户端 + 可选 Playwright)
↓
2. Transformers 管线(严格顺序):
rawHtml → html(去噪)→ markdown → metadata → links → images
↓
3. 按 formats 输出: markdown / html / json / screenshot
关键实现要点:
- HTML→Markdown 别用 Python 现成库硬扛 。可参考 Firecrawl 用独立进程/服务做转换(Python 可考虑
markdownify+ 自定义 boilerplate 过滤,或用已有的 Crawl4AI 输出)。⚠️ 如果追求高质量,Firecrawl 用的 Go 库firecrawl/html-to-markdown是开源可复用的。 - 去噪是关键质量分水岭 :移除 script/style/nav/footer/广告,保留正文结构。Firecrawl 的
removeUnwantedElements.ts+ Go 转换器是核心。可借鉴 Crawl4AI 的 PruningContentFilter。 - 超时管理:三明治超时(整体 / 引擎 / 单 URL),防止慢页面卡死整个服务。
- 字符集处理 :Firecrawl 的 fetch 引擎先读 header charset → 再读 meta charset → UTF-8 兜底(
decodeHtmlBuffer),这是中文本地化最容易踩的坑。
7.3 L2:多引擎瀑布流(Firecrawl 灵魂,强烈推荐)
这是 Firecrawl 与普通爬虫框架的本质区别。若已有 Scrapling/Crawl4AI/BrowserUse 等多引擎抓取组件,天然适合改造成这个模式。
python
# 伪代码:Python 版引擎瀑布流
ENGINES = [
{"name": "cache", "quality": 1000, "features": {...}},
{"name": "crawl4ai", "quality": 50, "features": {"js": True, "actions": False}},
{"name": "scrapling", "quality": 20, "features": {"js": True}},
{"name": "httpx", "quality": 5, "features": {"js": False}},
]
async def scrape(url, options):
flags = build_feature_flags(url, options) # 如需要 JS 渲染?
candidates = [e for e in ENGINES
if support_score(e, flags) >= threshold]
candidates.sort(key=lambda e: e["quality"], reverse=True)
active = []
while candidates:
active.append(launch(next(candidates)))
done = await asyncio.wait(active + [waterfall_timeout()],
return_when=FIRST_COMPLETED)
for task in done:
result = task.result()
if quality_ok(result): # 内容非空 + 状态码 OK + 无错误
return result
active.remove(task)
要点:
- 质量评估三要素照搬:内容非空 + 2xx/304 + 无页面错误。不要只看状态码------200 但空页面是常见陷阱。
- 瀑布流超时(不是串行 try/catch):引擎慢就让下一个引擎并行顶上,先到先得。实测能显著降低 P95。
- Feature Flags:actions/screenshot/js/mobile 等决定哪些引擎可用。例如要截图就排除纯 HTTP 引擎。
- 代理升级:403/429 自动换 stealth 模式重试(如 Scrapling StealthyFetcher 可作为 stealth 引擎)。
- 缓存引擎 quality=1000 最先试:Redis 按 URL 缓存,命中直接返回(实测可带来数十倍加速)。
7.4 L3:Crawl 全站爬取
- 队列 :先 Redis 即可(去重用
SET NX),规模大了再上 PostgreSQL/Celery。 - 链接过滤链:12 步过滤照搬(excludes/includes 正则、深度、子域名、文件类型、robots.txt)。
- URL 去重 :Redis
crawl:{id}:url:{hash}NX 锁,24h TTL。 - Map 端点:优先 sitemap.xml,回退爬页面提取链接。
- 异步任务 + Webhook:jobId + 轮询 + webhook 通知。
7.5 L4:LLM 结构化提取(结合免费模型,性价比最高)
关键洞察 :Firecrawl 的 Extract 本质 = 抓取 + 一次 generateObject(JSON schema 约束输出)。用任何 OpenAI 兼容的免费/低成本模型即可复刻:
python
# 伪代码:LLM 提取(OpenAI 兼容 + 免费模型)
import json
from openai import OpenAI
client = OpenAI(base_url="https://api.example.com/v1", api_key=KEY) # 任意 OpenAI 兼容端点
def extract(urls, schema, prompt):
docs = [scrape(u) for u in urls] # 复用 L1/L2
md = "\n\n---\n\n".join(d.markdown for d in docs)
md = trim_to_tokens(md, max_tokens) # tiktoken 精确截断
resp = client.chat.completions.create(
model="deepseek-v4-flash",
response_format={"type": "json_object"}, # 或 json_schema
messages=[
{"role": "system", "content": build_system_prompt(schema)},
{"role": "user", "content": f"{prompt}\n\n{md}"},
],
)
return validate_json(resp.choices[0].message.content, schema)
借鉴的细节:
- Schema 规范化 :字段全 required +
additionalProperties: false(约束更严,输出更稳)。 - 模型分级:简单 schema 用便宜模型,递归/复杂 schema 用贵模型(对应免费模型 → 付费模型分级)。
- Token 截断 :先字符粗截(
maxTokens×5),再 tiktoken 精截,最后 2.8 chars/token 兜底。 - 重试降级:配额超限自动换备用模型(如智谱 glm-4-flash 可作 fallback)。
- DeepSeek 等模型对
json_schema支持差异 :用json_object+ 强 prompt 更稳(实测 deepseek 系列 schema 服从性优于 glm-4-flash)。
7.6 不建议照搬的部分(成本/复杂度陷阱)
| Firecrawl 能力 | 建议 | 原因 |
|---|---|---|
| Fire-engine 自研浏览器集群 | ❌ 不学 | 需要大量 infra(浏览器池、代理池、状态同步),自托管版也没有;用 Playwright 池 + stealth 替代 |
| FoundationDB 队列 | ❌ 不学 | 超大规模才需要,Redis/PostgreSQL 够用 |
| Engpicker AI 引擎选择(GPT 评估) | ⚠️ 简化 | 思路很好但每次评估调 LLM 有成本;先做域名→引擎映射表 + 失败惩罚分(本地统计),成熟后再上 LLM 评估 |
| Spark 自研模型 | ❌ 不学 | 大模型是另一个领域 |
| Go/Rust 混合 | ⚠️ 按需 | Python 生态用 markdownify/trafilatura 或子进程调 Go 库即可,不必一开始就搞 c-shared |
7.7 推荐技术路线(Python 实现)
阶段 0(地基):FastAPI 服务
├─ POST /v1/scrape {url, formats} → ScrapeEngine
├─ POST /v1/crawl {url, limit} → 队列 + 轮询
└─ POST /v1/map {url} → sitemap + 链接提取
阶段 1(引擎层):
├─ 引擎注册表:httpx(fast) / Scrapling(medium) / Crawl4AI(js+md) / StealthyFetcher(反爬)
├─ 瀑布流调度器(asyncio + 质量评估 + 超时)
├─ 缓存引擎(Redis,quality 1000)
└─ Transformers 管线(rawHtml → html → markdown → metadata → links)
阶段 2(Crawl + Map + 任务系统):
├─ Redis 队列 + 去重锁 + robots.txt 检查
├─ 链接过滤链(12 步)
└─ Webhook 通知
阶段 3(LLM 提取,接免费模型):
├─ /v1/extract {urls, schema, prompt}
├─ schema 规范化 + tiktoken 截断 + json_object 输出
└─ 模型分级:deepseek-v4-flash(默认)→ glm-4-flash(fallback)
阶段 4(可选增强):
├─ 域名→引擎经验表(简化版 Engpicker)
├─ 页面 diff 监控(Monitor 雏形)
└─ 结构化提取模板(product/menu/attributes)
7.8 合规红线(Firecrawl 也在强调)
- robots.txt 默认遵守(用户可配置跳过但要有默认)
- 限速/礼貌抓取:单域名 QPS 限制,防止封 IP 和法律风险
- 数据合规:PII 脱敏、完成后清理中间数据(ZDR 思想)
- License 提醒 :Firecrawl 本身是 AGPL-3.0,若要商业化自研,不要直接抄它的代码(AGPL 传染),参考架构思路即可;SDK 层才是 MIT。走"借鉴思路、自研实现"路线最安全。
8. 附录:源码关键路径索引
| 路径 | 内容 |
|---|---|
apps/api/src/scraper/scrapeURL/index.ts |
scrapeURL 主入口(52KB,核心编排) |
apps/api/src/scraper/scrapeURL/engines/index.ts |
引擎瀑布流核心算法(引擎表 + feature flags + 调度) |
apps/api/src/scraper/scrapeURL/engines/fetch/index.ts |
fetch 引擎(undici + 字符集处理) |
apps/api/src/scraper/scrapeURL/engines/fire-engine/scrape.ts |
Fire-engine 客户端 |
apps/api/src/scraper/scrapeURL/engines/index/ |
index 缓存引擎 |
apps/api/src/scraper/scrapeURL/transformers/index.ts |
Transformers 管线编排 |
apps/api/src/scraper/scrapeURL/transformers/llmExtract.ts |
LLM 提取(54KB,模型选择/截断/重试) |
apps/api/src/scraper/scrapeURL/transformers/agent.ts |
Agent transformer |
apps/api/src/scraper/scrapeURL/lib/abortManager.ts |
三级超时管理 |
apps/api/src/lib/engpicker.ts |
AI 引擎选择器 |
apps/api/src/lib/extract/fire-0/ |
新一代 Agent 提取管线 |
apps/api/src/lib/html-to-markdown-client.ts |
Go 转换服务客户端 |
apps/api/sharedLibs/go-html-to-md/html-to-markdown.go |
Go HTML→MD(GFM + 代码块保护) |
apps/api/src/lib/crawl-redis.ts |
Crawl Redis 状态 |
apps/api/src/services/index.ts |
索引缓存服务 |
apps/api/src/lib/robots-txt.ts |
robots.txt 解析 |
apps/api/src/lib/threat-protection/ |
威胁防护 |
apps/api/src/lib/keyless.ts |
免密免费额度 |
apps/api/src/config.ts |
全量配置项(zod schema,18830 字符) |
docker-compose.yaml |
自托管部署 |
examples/kubernetes/firecrawl-helm/ |
K8s Helm chart |
apps/test-suite/ |
评测套件(含 load-test) |
附:参考资料
- GitHub 仓库:https://github.com/firecrawl/firecrawl(2026-08-12 抓取,165.9K stars)
- 官方文档:https://docs.firecrawl.dev(sitemap 996 页,v2 API 54 端点)
- 自托管指南:https://docs.firecrawl.dev/contributing/self-host
- 评测方法论:Firecrawl Issue #3782/#3757/#3587(Scrape Quality Evals)