用 firecrawl-build-search:从查询出发,把网页发现写进产品代码

前言

给应用接网页数据时,很容易把「搜」和「抓」混成同一步。用户问的是「竞品最近改了什么定价」「这个库现在怎么配 retries」,手里并没有现成 URL。这时如果直接调抓取接口,流程会卡在「还没有地址」;反过来,如果只拿搜索摘要就生成答案,引用往往对不上正文。

搜索和抓取是两条不同的数据管道。前者从查询出发,负责发现、排序和挑源;后者从已知 URL 出发,负责把页面变成 Markdown 或结构化字段。Firecrawl 官方把这条分界写进了一组 Agent Skill:总入口是 firecrawl-build,专门处理「查询优先」的窄技能则是 firecrawl-build-search

这是什么

一句话定位:firecrawl-build-search 指导 AI 编程助手把 Firecrawl 的 /search 接到产品代码里——功能从查询开始,而不是从 URL 开始;需要时可以在同一次调用里给结果补上页面正文(官方文档把这叫通过 scrapeOptions 抓取搜索结果,Skill 文案里对应「optional hydrate」)。

它由 Firecrawl 维护,源码在 firecrawl/skills 仓库的 skills/firecrawl-build-searchSKILL.md 的 frontmatter 写明:

  • namefirecrawl-build-search
  • version0.1.0
  • license:ISC
  • author:firecrawl
  • homepage:https://www.firecrawl.dev

目录里目前只有这一份 SKILL.md,没有附带脚本或 references/。它不替代 API 手册,而是告诉 Agent:什么时候该用 /search,什么时候不该用,集成时该去读哪份语言文档。

需要先分清同一生态里的几套技能,避免装错、用错:

仓库 / Skill 解决什么
firecrawl/cli 的 CLI skills 当前会话里搜网页、抓页面(终端一次性任务)
firecrawl-build 把 Firecrawl 写进应用的伞形技能:选型、鉴权、路由到具体端点
firecrawl-build-search(本文) 已经确定产品行为是「先发现再抽取」时,专门接 /search
firecrawl-build-scrape 已经有 URL,做单页抽取
firecrawl-build-interact 抓完之后还要点击、填表、多步导航

官方 README 写得很直:任务是「现在帮我搜一下 / 抓一下」走 CLI skills;任务是「把 Firecrawl 加进这个代码库」走 build skills。firecrawl-build-search 属于后者。

核心功能与亮点

根据官方 SKILL.md、仓库 README,以及作为调用事实源的 Search 文档Node 源文档,能力可以收成下面几条。

1. 触发条件:起点是查询,不是 URL

Skill 要求在这些情况下使用 /search

  • 用户提出问题,产品必须先发现来源
  • 功能需要当前网页结果
  • 要把搜索词变成一份后续可抓取的页面短名单

一句话:URL discovery 是产品行为的一部分时,先 /search。已经拿到具体地址,就不要绕这一步,改走 firecrawl-build-scrape

2. 搜索与抽取默认分开,水合是可选项

默认建议有三条:

  1. URL 发现属于产品行为时,先调 /search
  2. 概念上把搜索和抽取分开,除非明确需要把搜索结果页本身也抓下来
  3. 成本和延迟敏感时,优先「先挑 URL,再选择性抽取」,而不是对全部命中做宽泛水合

对应到 API:不带 scrapeOptions 时,/search 返回标题、描述和 URL;加上 scrapeOptions(例如 formats: ["markdown"])才会在同一次调用里带上正文。官方 Search 文档把这两种做法写成:

  • 一步:搜索请求里带 scrapeOptions,适合「每个结果都要正文」
  • 两步:先 search,过滤后再对选中的 URL 调 /scrape,适合要筛选、排序、控制费用的场景

Skill 明确偏向后者,除非产品真的需要全量正文。

实现备注要求 Agent:

  • /search 当作 discovery、ranking 和 source selection
  • 写清楚产品要的是 snippet、URL 列表,还是完整页面内容
  • 保持查询契约稳定,这样后面的 scrape 逻辑才可预期

常见产品形态(均来自 Skill,不是自行编的案例)包括:带引用的回答生成、公司 / 竞品 / 主题发现、先产出网页短名单再深挖的调研流、查询到 URL 再交给 /scrape/interact 的管道。这里的「research workflow」指的是发现网页;搜论文是另一条面,见下文升级规则。

4. 升级规则写死,避免用错索引

Skill 把几条容易混的路标写进了 escalation:

  • 已经有 URL → firecrawl-build-scrape
  • 结果页还要点击或填表 → firecrawl-build-interact
  • 要搜的是已发表论文(生物医学 / 临床 / 生命科学文献,PubMed、bioRxiv、medRxiv,或 arXiv 预印本)→ firecrawl-research-index。给 /searchcategories: ["research"] 不会打到论文索引,它只是把普通网页搜索限制到研究类站点(列表里包含 PubMed、bioRxiv、medRxiv、arXiv 和出版商站点),返回的是页面结果,没有摘要检索、相关论文扩展或全文段落
  • 要从 Issue、PR、README 或文档页回答开发问题 → firecrawl-developer-indexcategories: ["developer"] 同样有上述「不是专用索引」的限制

Search 功能文档与这条规则一致:research 是网站过滤器,不是论文库。

5. 具体怎么调 API,以语言文档为准

Skill 不内嵌 SDK 参数表,而是要求写集成代码前先读对应语言的 source-of-truth 页:

  • Node / TypeScript:https://docs.firecrawl.dev/agent-source-of-truth/node
  • Python:https://docs.firecrawl.dev/agent-source-of-truth/python
  • Rust / Java / Elixir / cURL:同一路径下替换语言名

这些页面才是方法名、参数和返回值的权威来源。Skill 负责「何时、为何」;「如何调用」以文档为准。

安装与启用

仓库 README 说明:这套 build skills 遵循 Agent Skills 格式,并作为插件提供给 Claude Code.claude-plugin/)、Cursor.cursor-plugin/)和 OpenAI Codex.codex-plugin/)。通用 SKILL.md 格式下,其他能发现技能目录的编程助手也可以使用;各工具具体落盘路径以安装器输出为准,这里不另行猜测。

官方给出的安装方式有三种,由宽到窄。

1. 一次装上 CLI skills + build skills(含本 Skill)

npx -y firecrawl-cli@latest init --all --browser

--all 会装 CLI、build 两段技能;--browser 打开浏览器完成 Firecrawl 登录。装完后需要重启 Agent,它才会发现新 Skill。

2. 只装 build skills 这一仓库

npx skills add firecrawl/skills

3. 只装 firecrawl-build-search 这一条

officialskills.sh 上的命令是:

npx skills add https://github.com/firecrawl/skills --skill firecrawl-build-search

也可以把该 GitHub 目录地址贴给编程助手,让它按 Agent Skills 流程安装。

产品侧鉴权,Skill 的 inputs 写了两项:

  • FIRECRAWL_API_KEY(必填):托管服务请求用。可在 firecrawl.dev/app 获取,写入 .env 或运行时环境
  • FIRECRAWL_API_URL(可选):自建 Firecrawl 的 base URL;只有不用托管的 api.firecrawl.dev 时才设

没有 Key 时,官方建议先走同仓库的 firecrawl-build-onboarding,它带浏览器授权流程。需要说明的是:Search 文档写过「不带 Key 也能试用,加上 Key 提高限流」;但 build Skill 把 Key 标成产品集成的必填项,按产品代码场景应以 Skill 为准。

SDK 安装以语言文档为准,例如:

npm install firecrawl
pip install firecrawl-py

Node 文档里的鉴权写法:

import { Firecrawl } from "firecrawl";

const client = new Firecrawl({
  apiKey: process.env.FIRECRAWL_API_KEY,
  // apiUrl: "https://api.firecrawl.dev" // 可选;也可读 FIRECRAWL_API_URL
});

Python 文档对应为 Firecrawl(api_key=os.environ.get("FIRECRAWL_API_KEY")),自建时再传 api_url

典型用法示例

下面提示词和代码均来自官方 Skill 或 source-of-truth / Search 文档,可按项目语言复现。先让 Agent 读对文档,再写集成。

1. 在 Cursor / Claude Code / Codex 里触发这条 Skill

用接近官方 description 的说法即可,例如:

这个功能从用户的自然语言问题开始,没有现成 URL。
请用 firecrawl-build-search,把 Firecrawl /search 接到现有后端:
先按查询发现来源,产出页面短名单;
不要一上来对全部结果做全文水合,成本和延迟敏感,挑完 URL 再选择性 scrape。

如果已经有明确地址,应改口「用 firecrawl-build-scrape 抓这一页」,避免 Agent 误走搜索。

2. 只发现:标题、摘要、URL

Node(source-of-truth):

const results = await client.search("site:docs.firecrawl.dev webhook retries");
for (const item of results.web ?? []) {
  console.log(item.url, item.title);
}

Python:

results = client.search("site:docs.firecrawl.dev webhook retries")
for item in results.web or []:
    print(getattr(item, "url", None), getattr(item, "title", None))

REST(Search 文档,POST /v2/search):

curl -s -X POST "https://api.firecrawl.dev/v2/search" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $FIRECRAWL_API_KEY" \
  -d '{
    "query": "firecrawl",
    "limit": 3
  }'

官方反复提醒:SDK 的 search() 不返回 { data: [...] } 网页结果在 result.web,新闻在 result.news,图片在 result.images。不要去读 result.data。cURL 的完整 JSON 里,未水合时 data 是按 web / news / images 分组的对象。

3. 同一次调用里给结果补正文(水合)

适合「每个命中都要 Markdown」的场景。Python Search 文档示例:

results = firecrawl.search(
    "firecrawl web scraping",
    limit=3,
    scrape_options={
        "formats": ["markdown", "links"]
    }
)

Node:

const results = await firecrawl.search("firecrawl", {
  limit: 3,
  scrapeOptions: { formats: ["markdown"] }
});

带上 scrapeOptions 后,命中会从轻量结果对象变成带正文的 Documentscrape 端点上的选项大多可以通过 scrapeOptions 传到 /search(Search 文档说明:除 Change-Tracking 等少数能力外,scrape 选项可用于 search)。

4. 两步:先短名单,再选择性抓取(Skill 默认更推荐)

Search 文档中的两步写法:

results = firecrawl.search("firecrawl web scraping", limit=5)

for item in results.web or []:
    page = firecrawl.scrape(item.url, formats=["markdown"])
    print(page.markdown[:200])

产品代码里通常会在两步之间加过滤:按域名、标题、还是 ignoreInvalidURLs: true 丢掉后续端点无法抓的地址。Node 复杂示例里还出现过 sources: ["web", "news"]tbs 时间过滤、location 本地化等参数,以当前语言文档为准,不要从过期博客抄字段。

limit 在指定多个 sources 时是按来源类型分别封顶limit: 5sources: ["web", "news"] 最多返回 5 条网页 + 5 条新闻。不同来源若要不同 limit 或不同 scrapeOptions,官方要求拆成多次调用。

适用场景与注意事项

适合

  • Agent 工作流里要把「网页搜索」做成一次工具调用,起点是用户问题
  • 调研、竞品跟踪、带引用问答:先得到排序后的页面列表,再决定抓哪几篇
  • 查询到 URL 的管道,下游再接 /scrape/interact
  • 明确需要「搜索结果带全文」时,用 scrapeOptions 一次拿回 Markdown / HTML / links

不适合,或应改走其他 Skill

  • 当前会话里临时搜一下、抓一下:用 firecrawl/cli,不要往业务仓库里写集成代码
  • 已经有 URL:firecrawl-build-scrape
  • 页面必须点击、填表才能看到内容:先 scrape 再 firecrawl-build-interact
  • 搜的是论文记录而不是网页:firecrawl-research-index,不要依赖 categories: ["research"]
  • 从仓库 Issue / PR / README 回答开发问题:firecrawl-developer-index

使用上的限制

  • 这是集成向导,不是完整 API 拷贝。参数、返回值以 docs.firecrawl.dev 的语言页为准;Skill 版本仍是 0.1.0,仓库 README 写明 evals 在首轮刻意延后
  • 宽泛水合会放大 credits 和延迟;Skill 默认建议选择性跟进抽取
  • 查询字符串要保持稳定(包括 site: 这类约束),下游 scrape 才好测、好缓存
  • Node SDK 文档声明引擎要求 Node.js >= 22;包名以当前 source-of-truth 为准(Node 为 firecrawl,Python 为 firecrawl-py
  • 第三方目录页上的安装次数、安全扫描分数不是官方数据,安装命令以 GitHub README 和 officialskills.sh 为准

小结

firecrawl-build-search 把「查询优先的网页发现」从抓取流程里拆出来:/search 负责发现和选源,抽取默认另走 /scrape,只有明确需要时才在搜索调用里做内容水合。它和 firecrawl-build 是同一仓库里的总入口与窄技能关系——前者决定要不要把 Firecrawl 写进应用、选哪个端点;本 Skill 在端点已经是 /search 时,约束集成方式和升级路径。

当前会话里的一次性联网,仍然走 CLI skills。把搜索写进产品代码时,从这份 Skill 开始,并在写调用前打开对应语言的官方文档。

官方地址:
https://github.com/firecrawl/skills/tree/main/skills/firecrawl-build-search

Search 文档:
https://docs.firecrawl.dev/features/search

目录页:
https://officialskills.sh/firecrawl/skills/firecrawl-build-search

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜