Firecrawl — 这是什么 · 全景 · 阅读地图
30 秒导读: Firecrawl 是一套开源的 web 数据 API:你给它一个 URL(网页、 也可以是 PDF/DOCX),它替你处理代理轮换、JS 渲染、反爬这些脏活,把页面变成 干净的 Markdown 或结构化 JSON——正好是喂给大模型的格式。它主要给 AI agent 当"眼睛和手":需要实时网页内容时调它。
1. 这是什么(零基础也能懂)
一句话定义
Firecrawl = 把"网页"变成"LLM 能直接吃的数据"的 API。 输入一个网址,输出一段 干净 Markdown 或一份符合你 schema 的 JSON。
解决什么问题 / 给谁用
假设你在写一个 AI agent,要它"读一下这个产品页,告诉我价格方案"。你会立刻撞上一堆 和 AI 无关的苦活:
- 页面是 JS 渲染的,
curl拿到的是空壳; - 网站有反爬 / 需要轮换代理 / 有速率限制;
- 拿到的 HTML 里全是导航栏、广告、脚本,真正的正文淹在噪声里;
- 你要的其实是结构化字段(价格、标题),不是一大坨 HTML。
Firecrawl 就是把这些苦活打包成一次 API 调用。README 的 "Why Firecrawl" 一节把卖点 列成:覆盖 96% 的网页(含 JS 重页面)、P95 延迟 3.4s、直接输出 LLM-ready 的 Markdown/JSON、 自动处理代理与反爬(README.md:52-62)。它给谁用:AI agent、RAG 管线、任何要"实时网页 上下文"的应用。
它能做什么(核心端点)
| 端点 | 干什么 | 同步/异步 |
|---|---|---|
| scrape | 单个 URL → Markdown / HTML / 截图 / JSON | 同步(等结果) |
| search | 搜索网页,并抓回结果页正文 | 同步 |
| map | 秒级发现一个站点的所有 URL | 同步 |
| crawl | 顺着链接爬完整站,抓所有页面 | 异步(返回 job id) |
| batch scrape | 一次异步抓成千上万个 URL | 异步 |
| extract / agent | 用自然语言 + schema 让 AI 跨页取数 | 异步 |
端点清单见 README.md:67-83;各端点的请求示例见 README.md:90-506。
用起来什么样
最小的一次调用(README.md:151-157 的 Python 例子):
from firecrawl import Firecrawl
app = Firecrawl(api_key="fc-YOUR_API_KEY")
result = app.scrape("firecrawl.dev") # 返回干净 Markdown
底下其实就是一个 HTTP POST(README.md:173-179):
curl -X POST 'https://api.firecrawl.dev/v2/scrape' \
-H 'Authorization: Bearer fc-YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{ "url": "firecrawl.dev" }'
拿回来的是 Markdown 正文,导航/脚本/广告已经被剥掉(README.md:189-199)。
一句话直觉
把 Firecrawl 当成 agent 的"网页读取器 + 提纯器":浏览器负责把页面渲染出来, Firecrawl 负责把渲染结果洗成模型看得懂的干净文本——你只管说"我要哪个 URL、要什么格式"。
2. 顶层全景(它大概怎么转)
怎么读这张图
从上到下是一次请求的生命周期。关键分叉在第二层: scrape 这类"要立刻拿结果"的
请求就地同步执行;crawl / batch / extract 这类"活很重"的请求丢进队列,由后台
worker 慢慢做,先返回一个 job id 让你之后来查。
HTTP 请求 (POST /v2/scrape | /v2/crawl | ...)
│
┌───────────────▼───────────────┐
│ 控制器层 (Express) │
│ routes/v2.ts → controllers/ │ ← 鉴权/限流/扣费中间件
│ v0 | v1 | v2 │
└───────────────┬───────────────┘
同步就地执行 │ 重活入队
┌──────────────────────┴───────────────────────┐
▼ ▼
┌────────────────────┐ ┌────────────────────────┐
│ scrape 控制器 │ │ 任务队列 NuQ │
│ 信号量占并发 → │ │ (自建, Postgres 背书) │
│ processJobInternal │ │ │ │
└─────────┬──────────┘ │ ▼ │
│ ← 两条路最终都汇到抓取内核 │ 后台 worker │
│ │ + WebCrawler 发现链接 │
└───────────────┬────────────────────┘ (逐个 URL 再走内核) │
▼
┌──────────────────────────────┐
│ 抓取内核 scrapeURL │ ← 一次"抓一个 URL"的编排器
└──────────────┬───────────────┘
▼
┌───────────────┬──────────────────┬────────────────────┐
▼ ▼ ▼ ▼
┌─────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 引擎系统 │ │ 转换流水线 │ │ 微服务 │ │ 存储/索引 │
│ engines │ │ transformers │ │ playwright / │ │ (缓存/GCS) │
│ 打分+回退│ │ HTML→MD、抽取 │ │ html-to-md │ │ │
└─────────┘ └──────────────┘ └──────────────┘ └──────────────┘
部件一句话职责
| 部件 | 干什么 | 在哪(相对 apps/api/src/) |
|---|---|---|
| HTTP 入口 | 建 Express app,挂载 v0/v1/v2 路由与错误处理 | index.ts(路由挂载见 :123-126) |
| v2 路由表 | 把 URL 路径映射到控制器,串上鉴权/限流/扣费中间件 | routes/v2.ts |
| 控制器层 | 每个端点一个控制器,校验入参、编排执行、组织响应 | controllers/v0 · v1 · v2/ |
| 抓取内核 scrapeURL | "抓一个 URL"的核心编排:选引擎、跑转换、容错重试 | scraper/scrapeURL/index.ts |
| 引擎系统 engines | 一堆抓取后端(fetch/playwright/fire-engine/pdf…),按能力打分排回退 | scraper/scrapeURL/engines/ |
| 转换流水线 transformers | 把原始 HTML 洗成 Markdown、再按需 LLM 抽取成 JSON | scraper/scrapeURL/transformers/ |
| 爬虫 WebCrawler | 爬站时发现并过滤链接、读 sitemap | scraper/WebScraper/crawler.ts |
| 任务队列 NuQ + worker | 自建队列(Postgres + RabbitMQ + Redis)+ 后台 worker 执行异步作业 | services/worker/nuq.ts · scrape-worker.ts |
NuQ 三系统各司其职(详见 04 章):Postgres 是作业表 + 状态机的事实源、RabbitMQ 做预取与完成通知、Redis 做团队/爬取级并发信号量。上图里"Postgres 背书"是这套组合的简写。