首页
/ CrewAI FirecrawlCrawlWebsiteTool:让 Agent 爬取整个站点并转换为干净 Markdown 的完整指南

CrewAI FirecrawlCrawlWebsiteTool:让 Agent 爬取整个站点并转换为干净 Markdown 的完整指南

2026-09-06 20:39:06作者:裘晴惠Vivianne

本文基于 CrewAI 仓库中 FirecrawlCrawlWebsiteTool 的官方工具文档与源码实现,完整讲解该工具的定位、安装方式、配置参数、初始化流程与 _run 执行链路。读完之后,你可以直接将该工具接入自己的 CrewAI Agent,让它通过一个 URL 爬取整个网站并得到可用于上下文检索的 Markdown/结构化数据,同时理解其底层的 URL 安全校验机制与测试验证方式。

工具定位:面向整站爬取的 Firecrawl 封装

工具文档对该工具的定义是:

Firecrawl is a platform for crawling and convert any website into clean markdown or structured data.

即 Firecrawl 是一个将任意网站爬取并转换为干净 Markdown 或结构化数据的平台,而 FirecrawlCrawlWebsiteTool 则是 CrewAI 官方工具集(crewai-tools)中将该能力封装为 Agent 工具的实现。与只抓取单页的 Scrape 类工具不同,该工具面向的是整站爬取(crawl):你只提供一个起始 URL,Firecrawl 会按照深度和数量限制把站点内的多个页面一并抓取,并统一输出为 Markdown,供 Agent 做知识库构建、站点调研或内容摘要等任务。

核心实现位于 firecrawl_crawl_website_tool.py,类结构非常简洁:

class FirecrawlCrawlWebsiteTool(BaseTool):
    name: str = "Firecrawl web crawl tool"
    description: str = "Crawl webpages using Firecrawl and return the contents"
    args_schema: type[BaseModel] = FirecrawlCrawlWebsiteToolSchema
    api_key: str | None = None
    config: dict[str, Any] | None = ...   # 默认爬取参数,见下文

需要注意一个版本口径:工具 README 声明 "This implementation is compatible with FireCrawl API v1",而源码 docstring 中描述的配置项(max_discovery_depthallow_subdomainsdelay 等)标注为 "Firecrawl v2 API"。从源码结构看,当前仓库实现已按 v2 参数体系组织默认配置,实际行为以源码 default_factory 中的默认值为准(详见后文"配置参数全解"一节)。

安装与前置准备

按照 README 的说明,准备工作分两步:

  1. 获取 API Key:从 Firecrawl 官方平台申请 API key,并设置为环境变量 FIRECRAWL_API_KEY
  2. 安装依赖:同时安装 Firecrawl Python SDK 与 crewai[tools] 包:
pip install firecrawl-py 'crewai[tools]'

这两条要求与源码声明完全对应。源码中通过 Pydantic 字段显式声明了运行时依赖与环境变量:

package_dependencies: list[str] = Field(default_factory=lambda: ["firecrawl-py"])
env_vars: list[EnvVar] = Field(
    default_factory=lambda: [
        EnvVar(
            name="FIRECRAWL_API_KEY",
            description="API key for Firecrawl services",
            required=True,
        ),
    ]
)

也就是说 FIRECRAWL_API_KEY 在工具元数据层面被标记为 required,CrewAI 框架在 Agent 装配工具时即可据此做依赖检查。此外,README 中的 Arguments 部分还说明了 api_key 构造参数:

  • api_key:可选。指定 Firecrawl API key;缺省时读取 FIRECRAWL_API_KEY 环境变量。
  • config:可选。包含 Firecrawl API 的爬取参数,详见后文。

还有一个源码级别的细节值得了解:如果你忘记安装 firecrawl-py,工具在初始化时不会静默失败,而是会交互式提示自动安装:

def _initialize_firecrawl(self) -> None:
    try:
        from firecrawl import FirecrawlApp
        self._firecrawl = FirecrawlApp(api_key=self.api_key)
    except ImportError:
        import click
        if click.confirm(
            "You are missing the 'firecrawl-py' package. Would you like to install it?"
        ):
            import subprocess
            subprocess.run(["uv", "add", "firecrawl-py"], check=True)
            from firecrawl import FirecrawlApp
            self._firecrawl = FirecrawlApp(api_key=self.api_key)
        else:
            raise ImportError(
                "`firecrawl-py` package not found, please run `uv add firecrawl-py`"
            ) from None

(见 firecrawl_crawl_website_tool.py#L82-L105)当用户确认后它会直接执行 uv add firecrawl-py 完成补装;拒绝则抛出带安装命令提示的 ImportError

快速上手

README 给出的标准用法示例如下(保留原文):

from crewai_tools import FirecrawlCrawlWebsiteTool
from firecrawl import ScrapeOptions

tool = FirecrawlCrawlWebsiteTool(
    config={
        "limit": 100,
        "scrape_options": ScrapeOptions(formats=["markdown", "html"]),
        "poll_interval": 30,
    }
)
tool.run(url="firecrawl.dev")

用法要点:

  • 工具通过 crewai_tools 顶层包导出,from crewai_tools import FirecrawlCrawlWebsiteTool 即可导入(导出注册见 tools/init.py);
  • tool.run(url=...) 的入参由 Pydantic 模式 FirecrawlCrawlWebsiteToolSchema 约束,只有一个必填参数 url(描述为 "Website URL"),这也是该工具交给 LLM 决策的唯一参数:
class FirecrawlCrawlWebsiteToolSchema(BaseModel):
    url: str = Field(description="Website URL")
  • config 中允许传字典,也允许传 Firecrawl SDK 的 ScrapeOptions 对象,因为它们最终都会被展开进 FirecrawlApp.crawl(...) 的调用参数(机制见后文 _run 解析一节)。

需要特别提醒的一处文档与实现差异:README 示例将 poll_interval 放进了 config,但当前源码中轮询间隔是在调用处硬编码的:

return self._firecrawl.crawl(url=url, poll_interval=2, **self.config)

(见 firecrawl_crawl_website_tool.py#L107-L112)从源码看,若你在 config 中再传一次 poll_interval,展开后会与关键字参数重复而引发冲突。因此按当前仓库实现,不要config 里手动指定 poll_interval,轮询间隔固定为 2 秒。

配置参数全解

config 参数的默认值由源码 default_factory 定义(firecrawl_crawl_website_tool.py#L50-L64),这是当前实现的事实基准:

参数 类型 默认值 含义
max_discovery_depth int 2 页面发现的最大深度
ignore_sitemap bool True 是否忽略站点 sitemap(True 表示不依赖 sitemap 发现页面)
limit int 10 最多爬取的页面数
allow_external_links bool False 是否允许爬取指向站外链接的页面
allow_subdomains bool False 是否允许爬取子域名
delay int | None None 请求间隔(毫秒)
scrape_options dict 见下 页面内容抓取选项

其中 scrape_options 的默认值为:

"scrape_options": {
    "formats": ["markdown"],      # 返回的内容格式
    "only_main_content": True,    # 只返回正文,排除 header/nav/footer
    "timeout": 10000,             # 抓取超时(毫秒)
}

对照 README 中给出的 "default configuration"(保留了原文档口径,便于与历史版本对照):

from firecrawl import ScrapeOptions

{
    "max_depth": 2,
    "ignore_sitemap": True,
    "limit": 100,
    "allow_backward_links": False,
    "allow_external_links": False,
    "scrape_options": ScrapeOptions(
        formats=["markdown", "screenshot", "links"],
        only_main_content=True,
        timeout=30000,
    ),
}

两者存在明显差异:README 使用 max_depth / allow_backward_linkslimit 为 100、超时 30 秒,而源码使用 max_discovery_depth / allow_subdomains 并新增了 delaylimit 收紧为 10、超时 10 秒。可以推断 README 的默认配置段落对应较早的 API 版本,而当前源码已按新参数体系重写。实际使用时请以源码 default_factory 为基准:如果你只想改个别项(例如把爬取上限放宽到 100 页),在 config 中只传覆盖项即可,其余项回落到上述源码默认值。

参数取舍上的实战建议(对应上表语义):

  • 控制成本与耗时limitmax_discovery_depth 是最直接的开关,小站调研用默认值即可,全站入库再调大;
  • 聚焦站点边界allow_external_linksallow_subdomains 默认 False,保证爬取范围不越出目标域名;
  • 内容形态scrape_options.formats 决定输出形态,Agent 上下文场景通常只保留 ["markdown"] 最省 token,需要截图或链接结构时再追加 screenshotlinks 等格式。

初始化流程:从 api_key 到 FirecrawlApp

工具实例化的完整调用链如下(见 firecrawl_crawl_website_tool.py#L77-L86):

  1. __init__(api_key=None, **kwargs) 先调用 BaseTool.__init__ 完成通用工具字段(name/description/schema 等)的初始化;
  2. 记录 self.api_key——若传入 None,则最终由 FirecrawlAppFIRECRAWL_API_KEY 环境变量读取;
  3. _initialize_firecrawl() 创建 FirecrawlApp(api_key=self.api_key) 实例并缓存到私有属性 self._firecrawlPrivateAttr,不参与 Pydantic 序列化)。

文件末尾还有一段防御性逻辑:在 firecrawl-py 可用时主动执行 FirecrawlCrawlWebsiteTool.model_rebuild()(并打上 _model_rebuilt 标记防止重复构建),用于让 Pydantic 模型正确解析对第三方类的引用;SDK 未安装时直接跳过,不影响模块导入。这个设计解释了为什么该工具文件顶部对 firecrawl 的 import 采用 try/except ImportError 包裹——未安装 SDK 时模块仍可被正常导入和发现,只在真正实例化时才触发依赖检查。

_run 深度解析:URL 安全校验与爬取调用

_run 方法只有三步(firecrawl_crawl_website_tool.py#L107-L112):

def _run(self, url: str) -> Any:
    if not self._firecrawl:
        raise RuntimeError("FirecrawlApp not properly initialized")

    url = validate_url(url)
    return self._firecrawl.crawl(url=url, poll_interval=2, **self.config)

其中最值得关注的是 validate_url。它来自 crewai-tools 统一的路径/URL 安全模块 safe_path.py,其模块 docstring 明确说明目的是"防止工具在运行时接受用户或 LLM 可控输入时发生未授权文件访问和 SSRF(服务端请求伪造)"。对 URL 的校验规则(safe_path.py#L198-L260):

  • 协议白名单:完全禁止 file://,只允许 http / https,且必须可解析出 hostname;
  • DNS 解析 + 私网拦截:对主机名做真实 DNS 解析,任何解析结果落入私网/保留网段的 URL 直接拒绝。被拦截的 IPv4 网段包括 10.0.0.0/8172.16.0.0/12192.168.0.0/16127.0.0.0/8169.254.0.0/16(云元数据地址)和 0.0.0.0/32;IPv6 侧拦截 ::1/128::/128fc00::/7(ULA)与 fe80::/10(链路本地)。IPv4-mapped IPv6 地址(如 ::ffff:127.0.0.1)会先解包为 IPv4 再比对,避免绕过;
  • 解析失败的保守策略:主机名无法解析、IP 无法解析为合法地址时,一律按"不安全"处理(block it);
  • 逃生开关:设置 CREWAI_TOOLS_ALLOW_UNSAFE_PATHS=true 可跳过校验(官方注释明确"不推荐在生产环境使用");多租户托管场景还可设置 CREWAI_TOOLS_FORCE_SAFE_PATHS=true 强制保持校验、禁止租户自行关闭。

这意味着:由于爬取 URL 往往由 LLM 在运行期生成,CrewAI 在把 URL 交给 Firecrawl 之前先做了一道 SSRF 防线,防止 Agent 被诱导去请求内网服务或云元数据端点。理解这一点,你就能明白为什么该工具"不能用于爬取内网页面",以及托管部署时相关环境变量的意义。

最后,self._firecrawl.crawl(url=url, poll_interval=2, **self.config)config 字典逐项展开为 Firecrawl SDK crawl 方法的 kwargs,poll_interval=2 表示每 2 秒轮询一次爬取任务状态(Firecrawl 的 crawl 是异步任务,SDK 内部轮询直到完成或进入可判定状态)。因此 config 中传普通 dict 还是 SDK 的 ScrapeOptions 对象都能工作——它们都是 crawl() 接口接受的参数形态。

集成测试验证

仓库为这个工具提供了基于 VCR(录制回放)的集成测试 firecrawl_crawl_website_tool_test.py

@pytest.mark.vcr()
def test_firecrawl_crawl_tool_integration():
    tool = FirecrawlCrawlWebsiteTool(config={
        "limit": 2,
        "max_discovery_depth": 1,
        "scrape_options": {"formats": ["markdown"]}
    })
    result = tool.run(url="https://firecrawl.dev")

    assert result is not None
    assert hasattr(result, 'status')
    assert result.status in ["completed", "scraping"]

该测试印证了前文的几个结论:config 使用 max_discovery_depth 这一 v2 风格参数名;limit/scrape_options 等覆盖项可自由组合;_run 的返回值是一个带 status 属性的结果对象,状态生命周期包含 scraping(进行中)到 completed(完成)——如果你的集成代码需要判断爬取是否真正拿到数据,应以 result.status == "completed" 为准,而不是仅检查对象非空。测试标记 @pytest.mark.vcr() 表示 HTTP 交互通过录制好的 cassette 回放,无需真实 API key 即可在 CI 中运行。

相关文档与工具规格

  • 本工具在仓库中随附的说明文档即 firecrawl_crawl_website_tool/README.md(本文的主要依据);
  • 官方站点文档对应页面为 firecrawlcrawlwebsitetool.mdx,包含安装与参数摘要;
  • 自动生成的工具规格文件 tool.specs.json 中收录了 FirecrawlCrawlWebsiteTool 的完整 schema:init_params_schemaapi_keyconfig 两个可选构造参数)、run_params_schema(必填 url)、env_varsFIRECRAWL_API_KEY,required)与 package_dependenciesfirecrawl-py),可作为该工具机器可读的接口契约参考。

小结

  • FirecrawlCrawlWebsiteTool 是 CrewAI 官方工具集中对接 Firecrawl 整站爬取能力的工具:给一个 URL,返回整站页面转换后的 Markdown/结构化数据(README)。
  • 接入只需:设置 FIRECRAWL_API_KEYpip install firecrawl-py 'crewai[tools]',然后 FirecrawlCrawlWebsiteTool(config={...}) + tool.run(url=...);漏装 SDK 时初始化流程会交互式提示 uv add firecrawl-py
  • 当前源码默认配置为 max_discovery_depth=2limit=10scrape_options={"formats": ["markdown"], "only_main_content": True, "timeout": 10000}allow_external_links/allow_subdomains 默认关闭;README 中的旧版默认配置(limit=100 等)仅作历史口径对照。
  • 执行链路 _run = 初始化检查 + validate_url SSRF 防御(仅 http/https,解析 DNS 并拦截私网/保留 IP)+ FirecrawlApp.crawl(url, poll_interval=2, **config);当前实现中 poll_interval 固定为 2 秒,不应再放入 config
  • 集成测试(VCR 回放)确认返回对象带 status 字段,取值包括 scrapingcompleted
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
916
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388