网页爬虫后端AI 应用【免费下载链接】firecrawlThe web data API to search, scrape, and interact at scale. 项目地址https://gitcode.com/GitHub_Trending/fi/firecrawl点击查看免费下载导读本文聚焦 Firecrawl 开源仓库中apps/api的日常开发流程完整讲解仓库根目录 AGENTS.md 所定义的先写端到端测试、再用pnpm harness启动整套服务验证、最后交给 CI的标准工作流。你将掌握 Firecrawl 后端代码修改的完整闭环如何编写带环境门控的 snips 测试、pnpm harness底层究竟启动了哪些服务与容器、以及如何只跑相关测试而非整条耗时测试套件。一、仓库结构一个 monorepo两类资产AGENTS.md开篇就点明了本仓库的定位Firecrawl 是一个 Web 抓取 APIweb scraper API当前目录是一个 monorepo多包单体仓库并给出了最核心的两类资产划分apps/api真正的 API 与 worker 代码Express 服务、爬虫调度、队列 worker、提取 worker 等全部在此apps/*-sdk各类语言 SDK例如js-sdk、python-sdk、go-sdk、rust-sdk、java-sdk、php-sdk、ruby-sdk、dot-net-sdk、elixir-sdk等。这一划分意味着对 API 的行为做任何改动都会直接辐射到所有 SDK 与调用方。因此 AGENTS.md 强调修改 API 时必须遵循一套固定的测试驱动步骤而不是直接pnpm start或盲目提交。二、修改 API 的四步标准工作流AGENTS.md明确给出了修改 API 时应遵循的四个步骤这也是整个文档的骨架编写端到端测试若尚不存在断言你的胜利条件win conditions编写代码实现胜利条件用pnpm harness jest ...运行测试推送到分支、打开 PR让 CI 验证胜利条件。下文逐一展开并结合仓库源码说明每一步的底层机制。三、第一步先写 E2E 测试snips3.1 为什么 E2E 优先于单元测试AGENTS.md的原文立场非常明确E2E 测试在 API 中被称为snips总是优先于单元测试。从仓库结构可以印证这一点apps/api/src/__tests__/snips/目录下存放了大量按 API 版本与功能维度组织的 E2E 测试包括v0/、v1/、v2/三个版本目录以及threat-protection、index-cache、wikipedia-url-parser、metadata-concat等专项测试文件。与snips并列的还有e2e_noAuth、e2e_withAuth、e2e_full_withAuth、e2e_v1_withAuth等目录它们同样是对真实 API 端点的端到端验证。整个apps/api/src/__tests__/之下单元测试*.test.ts且位于lib/等目录内占比很小绝大多数验证都发生在真实 HTTP 调用链路上。3.2 测试覆盖要求happy path failure pathAGENTS.md对测试覆盖提出了最低要求1 条 happy path主路径如果存在多条代码路径显著不同的 happy path鼓励多写1 条及以上 failure path失败路径验证异常分支与错误处理。以apps/api/src/__tests__/snips/v1/scrape.test.ts为典型例子其中既包含成功抓取的路径也包含itIf(...)门控下的各类边界与异常分支v1/deep-research.test.ts、v1/extract.test.ts等同样遵循主路径 失败路径的组织方式。3.3 超时规范必须使用scrapeTimeoutAGENTS.md特别强调在 API 测试中始终使用./lib中的scrapeTimeout来设置抓取超时。这里的./lib指的就是 apps/api/src/tests/snips/lib.ts其中定义// Due to the limited resources of the CI runner, we need to set a longer timeout // for the many many scrape tests export const scrapeTimeout 90000; export const indexCooldown 30000;从源码注释看scrapeTimeout取 90 秒是为了照顾 CI runner 资源有限、大量抓取测试并发执行时的真实耗时indexCooldown则用于索引类测试的冷却等待。测试中不要各自硬编码超时应统一引用该常量保证 CI 与本地行为一致。3.4 门控条件按依赖能力裁剪测试AGENTS.md指出这些测试会在多种配置组合下运行因此必须以如下方式对测试做门控gating需要fire-engineFirecrawl 的浏览器抓取引擎时!process.env.TEST_SUITE_SELF_HOSTED即仅在非自托管云托管/生产测试环境运行需要AI能力时!process.env.TEST_SUITE_SELF_HOSTED || process.env.OPENAI_API_KEY || process.env.OLLAMA_BASE_URL即非自托管环境、或自托管但配置了 OpenAI Key / Ollama 本地模型时运行。在 apps/api/src/tests/snips/lib.ts 中这些条件被封装成了一组可直接使用的辅助函数与布尔量export const TEST_SELF_HOST !!config.TEST_SUITE_SELF_HOSTED; export const TEST_PRODUCTION !TEST_SELF_HOST; export const HAS_AI !!(config.OPENAI_API_KEY || config.OLLAMA_BASE_URL); export const HAS_FIRE_ENGINE !!config.FIRE_ENGINE_BETA_URL; export const HAS_PLAYWRIGHT !!config.PLAYWRIGHT_MICROSERVICE_URL; export const HAS_SEARCH TEST_PRODUCTION || !!config.SEARXNG_ENDPOINT; export const describeIf (cond: boolean) (cond ? describe : describe.skip); export const concurrentIf (cond: boolean) (cond ? it.concurrent : it.skip); export const testIf (cond: boolean) (cond ? test : test.skip); export const itIf (cond: boolean) (cond ? it : it.skip);这意味着AGENTS.md中那两行环境变量门控在源码里已经内化为TEST_PRODUCTION、HAS_AI、HAS_FIRE_ENGINE等常量配合describeIf/itIf使用。例如 apps/api/src/tests/snips/v1/deep-research.test.ts 中describeIf(TEST_PRODUCTION || HAS_AI)(Deep Research, () { ... });只有在非自托管或自托管但配置了 AI 提供方时才执行不具备条件时整个 describe 块被describe.skip跳过测试套件在无 AI 的本地环境下依然可完整跑通。3.5 相关环境变量一览这些门控变量最终都来自 apps/api/src/config.ts 的 zod schema常用项如下环境变量默认值说明TEST_SUITE_SELF_HOSTED无可选自托管测试模式开关TEST_SUITE_WEBSITEhttp://127.0.0.1:4321测试站点地址本地对应test-siteTEST_API_URLhttp://127.0.0.1:3002被测 API 地址OPENAI_API_KEY无启用 AI 类测试OpenAI 提供方OLLAMA_BASE_URL无启用 AI 类测试本地 OllamaFIRE_ENGINE_BETA_URL无启用 fire-engine 相关测试SEARXNG_ENDPOINT无启用搜索类测试自托管时另外lib.ts中还有一条值得注意的规则当TEST_SUITE_WEBSITE是本地地址且处于自托管模式时会自动开启config.ALLOW_LOCAL_WEBHOOKS而在生产测试模式下禁止使用本地测试站点地址避免误打线上环境。四、第二步编写代码实现胜利条件在测试先行并定义好胜利条件后第二步就是实现这些条件。由于前面已经用describeIf/itIf把测试框定在了真实 API 链路上这一步的代码改动会自然落到 apps/api/src/controllersv0/v1/v2 三套控制器、apps/api/src/lib核心库逻辑与 apps/api/src/scraper抓取实现等目录中。AGENTS.md建议在构建 TODO 列表时始终把这四步记在心里即每个任务都应当以测试 实现 验证 提交为单位闭环推进。五、第三步用pnpm harness运行测试5.1 harness 是什么AGENTS.md明确指出pnpm harness是一条帮你把 API server 和 workers 拉起来用于跑测试的命令不要手动pnpm start。在 apps/api/package.json 中它的定义是harness: tsx src/harness.ts也就是说pnpm harness command...实际执行的是tsx src/harness.ts command...入口在 apps/api/src/harness.ts。从 harness 源码可以确认它的能力远不止启动一个进程依赖安装与构建默认会执行pnpm install、pnpm buildAPI以及go mod tidy并编译sharedLibs/go-html-to-md为 c-shared 库用于 HTML 转 Markdown启动 API 与各类 workerAPIapi、队列 workerworker、提取 workerextract-worker、NUQ_WORKER_COUNT个 nuq-worker按NUQ_BACKEND选择nuq-worker或nuq-fdb-worker、nuq-prefetch-worker、nuq-reconciler-worker以及在启用 DB 认证时启动index-worker容器编排本地运行时自动用 Docker/Podman 拉起NUQ PostgreSQL 容器firecrawl-nuq-postgres、NUQ RabbitMQ 容器firecrawl-nuq-rabbitmqrabbitmq:3-management以及 FDB 后端所需的FoundationDB 容器foundationdb/foundationdb:7.3.63并在退出时优雅停掉这些容器就绪等待通过端口探测waitForPort等待 API 在config.PORT默认本地 3002 附近就绪后再执行测试命令。因此pnpm harness实际是一条一键拉起完整本地微服务环境的命令而非简单的进程启动器。5.2 三种启动模式harness 支持三种特殊启动参数见printUsage参数行为pnpm harness --start开发模式使用tsc-watch监听 TypeScript 编译编译成功后自动拉起服务代码变更触发重新编译与服务重启pnpm harness --start-built跳过依赖安装与构建直接以已构建产物启动服务pnpm harness command...生产模式安装依赖 → 构建 → 拉起服务 → 等待 API 就绪 → 执行你传入的命令如pnpm test:snipsAGENTS.md中推荐的正是第三种用法pnpm harness jest ...而仓库 CI 使用的实际命令为pnpm harness pnpm test:snips见 .github/workflows/test-server.yml。注意pnpm test:snips在package.json中定义为仅运行src/__tests__/snips/v1与src/__tests__/snips/v2两个目录下的用例。5.3 本地只跑相关测试全量交给 CIAGENTS.md特别强调完整测试套件耗时很长本地应只执行相关测试让 CI 去跑全量。结合 package.json 的脚本这一点有非常具体的落地方式# 仅跑 snips 中的 v1 / v2 用例注意先启动 harness pnpm harness pnpm test:snips # 也可以只针对某个具体测试文件 pnpm harness pnpm exec vitest run src/__tests__/snips/v1/scrape.test.ts此外 package.json 还提供了按鉴权维度切分的全量脚本pnpm test排除e2e_noAuth、pnpm test:local-no-auth排除e2e_withAuth、pnpm test:full排除两套 auth E2E。在改动只涉及某个 controller 或 lib 模块时配合这些粒度选择即可显著缩短本地反馈循环。5.4 运行与停止的工程细节harness 还处理了很多容易踩坑的工程细节值得开发者在阅读日志时留意输出按进程着色分组api绿色、worker蓝色、extract品红、nuq青色、index/go黄色等便于在多进程日志中快速定位优雅停机收到 SIGINT/SIGTERM 时按序终止所有子进程并停掉由它创建的 PostgreSQL / RabbitMQ / FoundationDB 容器容器运行时自动探测优先使用 Docker其次 Podman两者都不可用时抛出明确错误提示安装或手动设置NUQ_DATABASE_URL/NUQ_RABBITMQ_URL/FDB_CLUSTER_FILE尊重显式配置如果环境里已经设置了NUQ_DATABASE_URL、NUQ_RABBITMQ_URL或FDB_CLUSTER_FILEharness 会跳过对应容器的创建直接沿用外部连接。六、第四步推送分支、开 PR、让 CI 验证完成本地验证后工作流的收尾是推送到分支 → 打开 Pull Request → 由 CI 验证胜利条件。CI 的主测试工作流位于 .github/workflows/test-server.yml其中核心测试步骤正是pnpm harness pnpm test:snipsworking-directory: apps/api并通过npm_config_ignore_scripts: true避免重复编译被缓存的 native 库。从该工作流的矩阵与注释可以推断CI 会在多种配置组合下验证你的改动抓取引擎维度是否启用 fire-engine浏览器抓取代理维度是否启用代理搜索维度是否启用 searxngAI 维度是否配置 OpenAI / Ollama队列后端维度postgres与fdb两种 NuQ 队列后端工作流会分别启动 Docker Postgres 或 FoundationDB 容器。这正是AGENTS.md要求用环境变量门控测试的根本原因同一份 snips 测试必须能在这些矩阵组合中各自裁剪出可执行的子集而不会因缺少某类服务而大面积失败。CI 还会生成 JUnit 报告并发布测试汇总方便在 PR 上快速定位失败用例。七、实践要点与常见误区小结结合AGENTS.md与源码最后汇总几条实操要点不要手动pnpm start跑测试那是开发服务器入口测试必须通过pnpm harness拉起完整服务栈API worker 各类 NuQ worker 容器依赖否则会因缺少队列/数据库/抓取服务而得到错误结论先写测试再写代码以snipsE2E 定义胜利条件至少覆盖 1 条 happy path 与 1 条失败路径统一用scrapeTimeout从apps/api/src/__tests__/snips/lib.ts引入90 秒不要自行硬编码超时善用门控辅助函数describeIf/itIf/testIf结合TEST_PRODUCTION、HAS_AI、HAS_FIRE_ENGINE等常量让同一套测试在不同 CI 矩阵下自动裁剪本地聚焦、CI 全量完整套件耗时长本地用pnpm harness pnpm test:snips或定向 vitest 命令验证相关用例即可全量验证交给 PR 上的 CI留意 harness 的容器管理本地首次运行会自动构建并启动 PostgreSQL / RabbitMQ / FoundationDB 容器请确保 Docker 或 Podman 可用若已有外部依赖则通过NUQ_DATABASE_URL、NUQ_RABBITMQ_URL、FDB_CLUSTER_FILE环境变量跳过容器创建。按照这套流程每次 API 改动都能在本地获得接近生产环境的验证反馈并通过 CI 矩阵覆盖到多种运行配置从而保证 Firecrawl 这条搜索 → 抓取 → 交互的链路在版本演进中持续可靠。赞分享网页爬虫后端AI 应用【免费下载链接】firecrawlThe web data API to search, scrape, and interact at scale. 项目地址https://gitcode.com/GitHub_Trending/fi/firecrawl点击查看免费下载相关推荐Firecrawl 贡献者开发指南E2E 测试驱动、harness 本地调试与 knip 检查全流程Firecrawl 贡献者开发指南E2E 测试驱动、harness 本地调试与 knip 检查全流程 Firecrawl 是一个面向大规模搜索、抓取与交互场景网页爬虫后端AI 应用AutoGPT PR 端到端手动测试技能基于 Docker Compose、agent-browser 与 API 证据链的 E2E 测试工作流AutoGPT PR 端到端手动测试技能基于 Docker Compose、agent browser 与 API 证据链的 E2E 测试工作流 AutoGP人工智能AI Agent自主智能体Agent 工作流工作流自动化后端前端RisingWave 连接器开发指南基于 RiseDev 的一体化开发环境与 E2E 测试工作流RisingWave 连接器开发指南基于 RiseDev 的一体化开发环境与 E2E 测试工作流 RisingWave 支持大量外部连接器Source 与数据库流处理后端数据工程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考