
Draco 是一个用 Rust 编写的、可以自托管的 Firecrawl 替代方案核心形态是单文件二进制single-binary下载后直接运行就能提供网页转 Markdown 的抓取能力。正在做 RAG、知识库或大模型应用的读者最常见的一个需求就是把一个网页或一堆网页转成干净的 Markdown再塞进向量库或直接喂给模型。Firecrawl 这类云端服务能解决这个问题但免费额度、按量计费、数据经过第三方这几个点长期用起来总会让人不踏实。Draco 的方向就是把这套能力搬到自己的服务器上。如果你正在选型网页转 Markdown 的服务或者好奇 Rust 写的自托管抓取工具到底能不能在普通机器上跑起来这篇文章值得看完。我会按实际部署顺序拆先讲这类工具到底解决什么问题再讲 single-binary 部署省了哪些事然后跑通单条抓取和批量爬取最后说 Rust 技术栈带来的边界、编译坑和排查顺序。项目具体接口名可能和版本有关所以我讲通用形态为主落地时以你下载版本的 README 为准。1. 先搞清楚 Draco 替代的 Firecrawl到底做了什么事1.1 URL 转 Markdown 是内容管线的第一步Firecrawl 本身是一条完整的“网页内容管线”给定一个 URL它会把网页正文提取出来去掉导航、广告、侧边栏、版权信息输出干净的 Markdown同时保留标题、描述、站点名等元数据。对 RAG 项目来说这一步非常关键。直接抓 HTML 再喂给模型token 浪费严重导航和脚本碎片还会污染检索结果。Draco 作为替代品最核心的定位就是把这部分能力本地化。单二进制意味着不需要装 Node.js、Python 环境、Redis 或者其他伴生服务一个可执行文件就是一套完整的抓取服务。Rust 实现通常意味着更低的常驻内存、更少的部署依赖以及更可控的并发行为。1.2 自托管解决的是额度、隐私和成本Firecrawl 提供云端免费额度类似服务也不少。问题在于只要走云端就有三件事绕不开额度免费额度用完就要付费批量场景下账单涨得很快。数据隐私抓取内容会经过第三方服务器内部知识库或未公开资料不适合这么处理。稳定性远端服务的限速、接口变更、故障都会影响你的管线。自托管不是为了“免费”而是为了把抓取链路完全握在自己手里。你控制请求频率、请求头、超时时间、输出目录也承担运行和维护成本。1.3 选型前先确认自己的场景不是所有场景都需要自托管抓取工具。用下面几条判断如果只是偶尔抓几个网页云端服务的免费额度基本够用。如果有定时批量抓取、接口调用频繁、内容可能涉及内部信息自托管更值得。如果目标站点大量依赖 JavaScript 渲染先确认 Draco 有没有内置浏览器渲染能力。纯静态 HTML 抓取工具对这类站点会很吃力。如果需要登录态、会话、复杂反爬绕过这类开源抓取工具通常不是为对抗性场景设计的也不应该是这类工具的主要用途。我的建议先拿 10 个真实页面跑一轮看 Markdown 质量能不能达到直接入库的水平。很多工具“能抓”和“抓得干净”是两回事。2. 部署前先摸清环境和前置条件2.1 single-binary 到底省了哪些事传统 Web 服务部署最常见的心智负担是“先装运行时再装依赖再配服务”。Draco 这类项目把这三步压缩成一步下载二进制文件给执行权限启动。前提是服务器架构和发布产物对得上。项目发布时通常会提供这几类产物平台常见架构说明Linuxamd64、arm64服务器最常用macOSaarch64、x86_64本地测试方便Windowsx86_64通常配合 MSVC 工具链Dockeramd64、arm64适合容器化部署如果你的机器架构比较冷门或者正好在版本发布周期内没有对应产物就只能走源码编译。所以 Rust 工具链的准备工作也需要了解。2.2 机器配置和网络要求单二进制运行本身不挑机器。一个 1 核 1G 的 VPS 跑单条抓取通常没问题但要注意内存并发数开得高或者目标页面特别大内存会涨。Rust 服务常驻内存相对低但不要因为“低”就无限开并发。磁盘抓取结果会写成 Markdown 文件或 JSON批量任务要预留足够磁盘。出网带宽抓取目标站点需要稳定的出网能力目标站点加载慢时超时时间要被拉长。我实际测试这类工具时一般先用小内存机器验证“能不能跑”再用真实目标页面验证“抓得稳不稳”。两件事不能混为一谈。2.3 需要源码编译时先把 Rust 环境准备好如果拿不到预编译二进制或者想改代码重新构建需要准备 Rust 环境。常见安装方式curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh source $HOME/.cargo/env rustc --version cargo --version如果你在国内网络环境crates.io 默认源通常很慢先把国内镜像配上。这里以 rsproxy 的配置为例中科大、字节跳动的镜像源也可以cat ~/.cargo/config.toml EOF [source.crates-io] replace-with rsproxy-sparse [source.rsproxy-sparse] registry sparsehttps://rsproxy.cn/index/ [registries.rsproxy] index sparsehttps://rsproxy.cn/index/ [net] git-fetch-with-cli true EOF配置完成后先跑一个简单项目验证下载和编译链路再进入 Draco 源码构建顺序比较稳。Windows 上要特别注意工具链。Rust 默认安装的是 MSVC 工具链需要 Visual Studio Build Tools 里的 C 构建工具不然编译到一半会报 linker 错误。如果不想装 MSVC可以安装 GNU 工具链但后面依赖原生库时可能遇到兼容问题。我的建议是 Windows 上优先把 VS Build Tools 装好然后用默认 MSVC 工具链。2.4 构建命令和产物位置源码项目一般遵循 Cargo 标准流程git clone 项目仓库地址 cd draco cargo build --release编译产物在target/release/目录下文件名通常是项目名。编译时间取决于依赖数量Rust 全量依赖编译会比较久。第一次直接用--release构建不要中途频繁改配置重编否则增量编译缓存会被反复重置。3. 单条抓取跑通从启动服务到拿到 Markdown3.1 先看启动参数再启动服务拿到二进制后先不要急着加参数跑。运行--help花两分钟看支持哪些子命令./draco --help常见设计有两种一种是一行命令直接进入服务模式默认监听某个端口另一种是拆成子命令比如draco serve启动服务、draco scrape做一次性抓取。不同项目习惯不同我这里统一以“服务模式 HTTP 接口”为例实际命令以你下载版本的 README 为准。启动服务时需要关注的配置项监听地址默认127.0.0.1只允许本机访问如果要让其他服务器调用要改成0.0.0.0并配合防火墙做限制。端口默认端口各异避免和已有服务冲突。并发上限控制同时处理的抓取任务数。超时时间单次抓取的最长等待时间。示例./draco serve --host 127.0.0.1 --port 3000如果启动成功日志里应该能看到监听地址。看不到监听信息说明配置没生效先检查端口是否被占用。3.2 用 curl 发一次最小抓取请求假设服务提供的是类 Firecrawl 接口请求通常长这样curl -X POST http://127.0.0.1:3000/v0/scrape \ -H Content-Type: application/json \ -d {url: https://example.com}返回结果一般是一个 JSON包含success任务是否成功data.markdown网页正文转成的 Markdowndata.metadata标题、描述、域名等元信息data.html是否保留原始 HTML第一次测试不要用复杂首页选一个结构简单的静态文章页最好是你自己的站点或公开文档页。这样容易判断 Markdown 质量是否合理。如果连简单页面都抓得不对问题大概率出在配置或抓取策略而不是目标站点复杂。3.3 判断抓取结果是否合格拿到返回的 Markdown 后不要只看“有没有内容”要按这套标准检查标题有没有进到 Markdown 的 H1。正文段落是否完整有没有漏掉副标题、列表、代码块。导航、页脚、广告、脚本内容是否被剔掉。图片链接是完整 URL 还是相对路径。表格是否被正确转成 Markdown 表格而不是堆成一段文本。只要这五点检查通过这条数据就可以进入后续切片和向量化。3.4 单条抓取常见失败表现超时页面太大或目标站点太慢。先调大超时时间再看页面本身是否正常。403目标站点拒绝默认 User-Agent 或来源 IP。先确认是否遵守目标站点规则再考虑合适请求头。空 Markdown页面可能依赖 JavaScript 渲染或者正文结构特殊。换一个静态页面对比测试能确认是工具问题还是目标站点问题。4. 批量爬取范围、速率和失败重试4.1 单条接口和批量接口是两套能力单条抓取能跑通不代表批量任务可以直接上线。批量爬取要额外处理从哪个页面开始最多抓多少条是否只抓同域名允许哪些路径排除哪些路径页面之间的间隔时间失败任务是否重试输出文件怎么命名往哪个目录写如果项目提供类似/v0/crawl的接口通常流程是提交起始 URL 和限制参数服务返回一个任务 ID然后轮询任务状态。# 提交爬取任务 curl -X POST http://127.0.0.1:3000/v0/crawl \ -H Content-Type: application/json \ -d {url: https://docs.example.com/, limit: 20, maxDepth: 2} # 轮询任务状态 curl http://127.0.0.1:3000/v0/crawl/task-id轮询结果里应该有 completed、failed、total 之类的计数。看到 completed 数和 total 对不上不要急着加并发先看失败原因。4.2 范围控制比并发数更重要批量爬取最容易翻车的不是性能而是爬出不相关页面把输出目录塞满。下面几个控制方式很关键参数作用建议limit最大抓取页数必设第一次先设 10maxDepth从起始页向下跳几层文档站设 2 到 3 够用allowedDomains只允许目标域名必设防止跑偏pathPatterns只匹配指定路径站点结构混乱时很有用如果工具没有提供这么多选项至少也要在调用外面做一层 URL 白名单过滤。批量抓取前先用小 limit 跑一遍比如 10 个页面检查每个页面是否在预期范围内。4.3 速率控制和输出命名批量任务不是越快越好。对目标站点造成过大请求压力既不合规也可能导致 IP 被封。至少要做到每个页面之间设置延迟比如 500ms 到 1s。并发数从 1 开始稳定后再逐步增加。遵守目标站点 robots.txt明确不允许抓取的部分不要硬抓。重试次数不要无限重试。4xx 类错误直接跳过5xx 类可以重试 1 到 2 次。输出命名也很影响后续处理。比较好的方式是按 URL 路径生成目录结构或者用 URL 哈希做文件名避免冲突。批量任务跑起来后先盯着前 5 分钟的输出和日志。这个阶段能发现的问题比跑完再看结果要少浪费很多时间。5. Rust 技术栈带来的优势和边界5.1 为什么 single-binary 在 Rust 领域特别顺Rust 编译产物默认静态链接大部分依赖所以“一个二进制文件”能直接拷到服务器上运行不依赖目标机器上的运行时。相比 Node.js 项目要带一整个 node_modules、Java 项目要带 JRE 或一堆 jarRust 的部署形态确实更适合自托管。这一点对抓取服务很现实。抓取服务经常要放在离目标站点网络更近的机器上或者放在多台小服务器上做分发单二进制拷贝起来非常方便。很多 Rust 服务用 actix-web 或 axum 这类框架提供 HTTP 接口启动快、并发承载稳定也适合这种单文件服务场景。5.2 资源占用和并发特征没有实际测试数据之前不要轻易说“Rust 占用一定低”。更准确的说法是Rust 项目通常起步内存占用低不会有 JVM 或 Node 运行时那种固定开销并发行为也更可控。但具体内存上限取决于你开的并发数、单页面大小和依赖库实现。我建议批量跑之前做一次简单的资源摸底# 观察进程内存和 CPU top -p $(pgrep draco)看两个点空闲时内存是多少跑并发抓取时内存峰值是多少。如果任务一多内存涨得夸张优先降低并发数而不是加内存。换机器不如先优化参数。5.3 源码构建的边界Rust 源码构建有几个常见的“看起来是功能问题其实是环境问题”的情况cargo build卡在下载依赖先检查镜像配置是否生效。Windows 报 linker 错误检查是否安装了 VS Build Tools或工具链是否为 MSVC。编译失败但错误信息指向某些系统库可能缺少对应的原生开发库比如 openssl、libxml2 相关。这些问题的核心是先把构建环境弄干净再判断代码有没有问题。不要一上来就怀疑项目代码先看错误信息里有没有路径、库文件、连接器相关的关键词。5.4 对竞品生态的兼容程度Firecrawl 生态里很多人已经写好了调用脚本例如用firecrawlSDK 或直接 HTTP 请求。如果 Draco 做得足够兼容你只需要改 base URL 就能切换过去。但“兼容”和“完全一致”是两回事测试时要注意同样的请求参数返回结构是否一致。多余字段是忽略还是直接报错。异步任务的状态轮询逻辑是否一致。建议保留一层自己的调用封装不要把 SDK 调用散落在业务代码里。这样切换服务时只需要改一处配置。6. 常见问题排查按顺序走别乱动参数6.1 排查顺序遇到问题我一般按这个顺序排查先看现象报错、卡住、无输出、输出乱码是哪种。再换一个已知最简单的 URL排除目标站点因素。看服务日志有没有请求进来、有没有超时、HTTP 状态码是什么。看资源占用内存、CPU、磁盘是否被打满。看参数超时、并发、User-Agent、输出路径是否有问题。最后才考虑是不是工具本身的功能限制。不要一上来就改并发或换二进制版本那样只会让问题更难定位。6.2 抓取结果不干净的常规原因现象常见原因处理方向Markdown 里全是导航正文提取策略不适合该站点换页面测试看是否普遍正文为空但有 HTML页面依赖 JS 渲染确认是否支持浏览器渲染返回验证页目标站点有防护遵守规则避免高并发图片链接失效懒加载未触发看原始 HTML 是否含完整链接表格变成纯文本表格结构太复杂检查提取策略是否识别 table对这些情况先看返回的原始 HTML 里是否包含正文。如果不包含基本可以判断是需要浏览器渲染或目标站点有防护如果包含但 Markdown 提取失败那才是提取策略的问题。6.3 批量任务中断的处理方式批量抓取最怕跑到一半服务重启还要从头再来。比较好的实践是输出文件用任务 ID 加序号命名避免覆盖。定期把已完成 URL 记录到清单文件重启后跳过已完成部分。每次任务结束后看一眼失败数量针对失败原因分类而不是无脑重跑。如果项目本身不支持断点续跑也可以在外部用脚本维护“已完成 URL 集合”和“剩余 URL 列表”。抓取工具的职责是抓取任务编排的职责可以留在你的脚本里。7. 是不是值得换成 Draco我的判断标准7.1 适合 Draco 的三种情况不是所有项目都需要从 Firecrawl 迁到 Draco但以下三种情况我会优先考虑你的调用量已经超过云端免费额度且没有为 API 按量付费的预算。抓取内容涉及内部资料、未公开文档不适合经过第三方服务。你需要把抓取服务部署到多台小机器上单二进制分发最省事。反过来说如果团队里已经有一整套 Firecrawl SDK 调用链而且用量不大迁移带来的收益可能不够覆盖改造成本。先用兼容方式验证再考虑切换。7.2 上线前的三件事不管选哪个方案正式接入业务前建议先过三关拿 10 个真实目标页面跑单条抓取评估 Markdown 质量。拿 20 到 50 页小批量跑一次确认稳定性、失败率和资源占用。确认输出目录、文件命名、日志记录都符合你的管线要求。这三件事过了再谈并发、接口封装和更复杂的调度。7.3 长期维护要考虑什么自托管服务不是装完就不管了。后续要关注项目是否持续更新目标站点结构变化后提取规则是否需要调整。Rust 版本升级是否影响构建依赖是否有安全更新。服务器日志和监控有没有接好任务失败能不能第一时间发现。输出格式变化时下游的切片、清洗、入库逻辑是否需要同步调整。这些看起来和 Draco 本身无关但真正影响你体验的往往是这些外围条件。结尾Draco 这类项目真正值钱的地方不是“我能抓网页”而是能把网页变成可复用的 Markdown 数据并且部署形态足够简单。单二进制和 Rust 的组合让自托管这件事的门槛降到了很低。如果你只是偶尔抓几个页面云端服务的免费额度可以先用着。如果要做知识库、跑定时任务、处理内部文档又不想让内容经过第三方就可以把 Draco 这类自托管方案纳入选型。落地前先做三件事拿简单页面验证 Markdown 质量拿 20 页小批量验证稳定性确认输出目录和任务命名规则。这三件事过了再谈并发和接口对接。踩过几次之后我发现很多自托管项目真正的问题不是能力不够而是前置环境、目标页面格式和任务编排没有处理好。先把最基础的链路跑稳比一开始就追高并发和完整功能更实际。