Firecrawl 从零到跑通:4 个实战场景把任意网页变成 AI 能用的干净数据
【免费下载链接】firecrawlThe context API to search, scrape, and interact with the web at scale. 🔥项目地址: https://gitcode.com/GitHub_Trending/fi/firecrawl
做 AI 应用最头疼的一步,往往不是写提示词,而是让大模型"看见"网页。你手动复制粘贴、还要把导航栏页脚广告全删干净,遇到 JS 动态加载的页面直接抓不到内容。Firecrawl(一个把网页变成大模型可用数据的开源 API)干的就是这件事:给它一个网址,还你干净的 Markdown 或结构化 JSON,代理、反爬、JS 渲染这些脏活它全包了。
它帮你省掉的活
- 输出即插即用:网页直接变成干净 Markdown,省掉 HTML 解析和清洗
- 多形态返回:Markdown、结构化 JSON、截图,一次请求按需选
- JS 重页面也吃得下:覆盖约 96% 的网页,含动态渲染内容,不用自己搭代理池
- 十几种语言 SDK:Python、Node.js、Go、Rust、.NET 都有官方客户端
- AI 助手原生集成:一条命令给 Claude Code 等 MCP 客户端装上,助手直接会抓网页
- 能自己部署:开源(AGPL-3.0),Docker Compose 一条命令起本地服务
从零到跑通:装 SDK 到第一次拿到 Markdown
你做什么:先决定路线。最快的是注册官方云版本拿一个fc-开头的 API key;想数据留在自己手里,就克隆仓库自部署。
自部署只需要三步(项目自带docker-compose.yaml):
- 克隆仓库:
git clone https://gitcode.com/GitHub_Trending/fi/firecrawl - 在项目根目录建一个
.env,写上USE_DB_AUTHENTICATION=false(先关鉴权把链路跑通,生产环境再补上认证和 TLS) - 运行
docker compose up -d
看到什么:服务起来后,本机3002端口就是 API 入口(Compose 默认只把这个端口映射到宿主机)。
第一次验证(Python SDK,Node.js 同理换成npm install firecrawl):
pip install firecrawl-py export FIRECRAWL_API_KEY=fc-YOUR_KEY # 自部署可留空from firecrawl import Firecrawl app = Firecrawl(api_key="fc-YOUR_KEY") # 自部署:Firecrawl(selfHosted=True, api_url="http://localhost:3002") doc = app.scrape("https://example.com", formats=["markdown"]) print(doc.markdown)看到带#标题的 Markdown 正文,而不是<div>标签,就对了。
遇到 X 怎么办:
- 报401:key 没配对。自部署时记得客户端加
selfHosted=True并指到本地地址 - 输出是一堆 HTML 标签:没指定输出格式,
formats=["markdown"]写全 docker compose up失败:先看docker compose ps哪个服务没起来,Playwright 容器首次拉镜像会比较慢,多等一会儿
到这里你就基本跑通了,下面全是实战。
场景一:抓单个页面,只要正文和关键字段
一行 scrape 调用,返回的就是能直接喂给大模型的 Markdown
scrape是整个工具里用得最多的一个调用,常用参数直接给默认值:
| 参数 | 建议值 | 作用 |
|---|---|---|
formats | ["markdown"] | 输出 Markdown,也可换json、screenshot |
onlyMainContent | True | 只保留正文,丢掉导航栏页脚 |
waitFor | 3000(毫秒) | 等待 JS 异步内容渲染完 |
timeout | 30000(毫秒) | 单页抓取超时上限 |
电商商品页这种 JS 渲染重的页面,完整调用长这样:
doc = app.scrape( "https://books.toscrape.com/", formats=["markdown", "json"], onlyMainContent=True, waitFor=2000, jsonOptions={"schema": {"type": "object", "properties": { "title": {"type": "string"}, "price": {"type": "number"}}, "required": ["title", "price"]}}, )为什么这样设:waitFor=2000让爬虫等 2 秒异步内容加载完;jsonOptions指定字段后,它按你的结构直接吐数据,比让大模型从 Markdown 里挖字段又快又准。
小贴士:抓出来全是菜单和页脚时,第一个该开的开关就是
onlyMainContent=True。
场景二:一个网站抓到底,先 map 再 crawl
盲目爬整站容易失控,标准姿势是先用map摸底(它只做链接发现,不抓内容,速度快):
links = app.map("https://books.toscrape.com", search="adventure") print(len(links.links), "个页面") # 先看看体量,再决定抓多少确认体量后开爬,limit一定给:
job = app.crawl("https://books.toscrape.com", limit=100, formats=["markdown"]) for page in job.data: print(page.metadata.source_url, page.markdown[:80]) print(f"完成:{len(job.data)} 页")你做什么:给limit=100设上限。看到什么:SDK 会自动轮询任务状态直到completed,返回每页 Markdown。遇到 X 怎么办:页面超过 limit 会被截断,把 limit 调大或按分类 URL 分批跑。
URL 列表已知、数量又多的情况,用批量抓取更划算:
job = app.batch_scrape([ "https://books.toscrape.com/", "https://books.toscrape.com/catalogue/", ], formats=["markdown"])一次请求丢几百个 URL 进去,服务端并发处理,比在 for 循环里逐个 scrape 快得多。
场景三:定时盯价格,页面一变就发现
每次抓取存一条记录,连成价格曲线
盯价格的核心思路:抓一次存一次,下次对比。一个能直接跑的 Python 脚本:
import json from firecrawl import Firecrawl app = Firecrawl(api_key="fc-YOUR_KEY") URL, STORE = "https://example-shop.com/item/123", "price.json" doc = app.scrape(URL, formats=["json"], jsonOptions={ "schema": {"type": "object", "properties": {"price": {"type": "number"}}}}) price = doc.json["price"] hist = json.load(open(STORE)) if os.path.exists(STORE) else [] hist.append({"ts": now, "price": price}) json.dump(hist, open(STORE, "w"))再挂一个定时任务,比如每天凌晨两点跑一次:
0 2 * * * /usr/bin/python3 /path/price_check.py为什么这样设:每天只抓一次、只取一个字段,token 和额度消耗都最低;历史存在本地 JSON 里,断网重跑也不丢数据。
如果盯的不是价格而是"页面内容有没有改"(竞品改版、文档更新),可以用官方演示项目里的 change tracking 玩法:把每次抓取结果做差异对比,只关注变了的部分。
进阶玩法:不用 URL、会点鼠标、装进 AI 助手
抓取结果可以逐次对比,页面文案一变就会被标记出来
Agent:描述需求,不给网址。你不知道数据在哪个页面时,直接把任务丢给 Agent:
result = app.agent(prompt="Find the pricing plans for Notion", model="spark-1-mini") print(result.data, result.data_sources) # 数据 + 来源 URL它自己会搜索、导航、取数。模型有两档:简单任务用spark-1-mini,便宜约 60%;跨站点对比、关键数据换回spark-1-pro。也可以用urls=[...]把它圈定在几个指定页面里。
Interact:抓完之后继续点。需要搜索框、翻页、登录后的页面时:
scrape = app.scrape("https://example-shop.com") app.interact(scrape.metadata.scrape_id, prompt="Search for 'mechanical keyboard'") app.interact(scrape.metadata.scrape_id, prompt="Click the first result")MCP:一条命令装进 AI 编程助手:
npx -y firecrawl-cli@latest init --all --browser重启 Claude Code、OpenCode 之类的客户端后,直接对助手说"查一下某个网页的内容"就行。
自部署上生产:仓库里带了 Kubernetes 清单和 Helm chart,放在examples/kubernetes/cluster-install/和examples/kubernetes/firecrawl-helm/,生产前记得把USE_DB_AUTHENTICATION打开并配好 TLS。
踩坑速查:4 个高频问题分步解决
现象:请求返回 401大概率原因:API key 没配对,或者自部署时地址指错。
- 终端执行
echo $FIRECRAWL_API_KEY确认变量读到了 - 自部署场景检查
selfHosted=True和api_url是否指向本机 3002 端口 - 云版本的话去控制台确认 key 没被禁用
现象:页面抓出来是空的大概率原因:JS 没渲染完就取了 DOM。
- 加
waitFor=3000再试 - 用浏览器手动打开该 URL,确认不登录也能看到内容
- 换个
formats验证返回里有没有metadata,确认请求本身通了
现象:任务超时或失败
- 把
timeout从 30000 提到 60000 - 降低单次
limit,大任务拆成多批 - 仍失败就隔几分钟后重试,目标站点可能在限流
现象:提示额度不足
- 云版本去控制台看剩余额度,用完就充值
- 回头检查是不是
limit设太大、batch_scrape一次丢了几千个 URL - 日常监控场景改用
map或只抓单页,别动辄 crawl 整站
现在就可以做的事
- 装好 Python SDK,跑通第一次
scrape,看到干净的 Markdown - 给一个你常看的网站写
map调用,摸清它的页面体量 - 挑一个商品或文档页,配上
jsonOptions只取你要的 2 个字段 - 把定时对比脚本挂上 crontab,先让它每天安静跑一周
- 有余力就上 Agent 和 MCP,让 AI 助手自己会查网页
参数没有唯一解,waitFor、timeout、limit都按你盯的网站慢慢调。跑起来之后,网页到你 AI 应用之间就只剩一次 API 调用了。
【免费下载链接】firecrawlThe context API to search, scrape, and interact with the web at scale. 🔥项目地址: https://gitcode.com/GitHub_Trending/fi/firecrawl
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考