16k 星的 anydoc:让 Firecrawl 帮你把 Word/PPT/Excel/PDF 全打成 Markdown 喂给 AI

上周把一份 30 页的合同 PDF 丢给 Claude Code,想让它帮我抠出违约条款、自动 diff 甲乙双方修改痕迹。结果它来回给我这样的反馈:

“无法读取该文件:PDF 内容可能需要 OCR。建议先把 PDF 转成可读文本再上传。”

我只能苦笑 —— 这已经是第 N 次了。我的日常工作流里,给 AI “喂资料” 是最大的隐性成本。一份合同要走 Pandoc,一份历史周报要走 mammoth,一份 PPT 要靠 LibreOffice 头出口转 Markdown…… 十次任务,五种工具,五种输出风格,表格常常错乱,编号常常乱跳,含中文段落更是灾难。

直到今天刷 GitHub Trending 看到 firecrawl/anydoc——16.7k stars、15 天涨上来、Firecrawl(那个把网页批量爬成 Markdown 的公司)亲自开源的” 全文档转 Markdown” 库,Rust 内核 + Node.js + Python + WASM 四种绑定,14 种格式统一输出中位数 4.4 毫秒

我装下来用了 20 分钟,第一个想法是:原来文档预处理才是 Agent 时代的第一道瓶颈,这件事应该早一年有人做

下面就拆开它看看 —— 一个用纯 Rust 写的、靠” 内容签名” 识别文件类型(不靠扩展名)、把 14 种格式收敛到同一份 Markdown 输出的工具,到底是怎么把 MarkItDown、Docling、Unstructured、Pandoc 这些老前辈全卷了一遍的。


一、项目背景:AI 时代,” 喂文档” 才是真正的最后一公里

先把问题摆在桌面上。

过去三年,整个 LLM 应用生态都在解决两件事:

  1. 怎么让模型更聪明 —— 这一条已经被卷到天花板,GPT-5、Claude Opus 5、Gemini 2.5、Kimi K3 选谁都不算丢人。
  2. 怎么把数据塞进模型 —— 这一条才是真正卡住大多数项目的地方

我自己的体感也是这样。Open Notebook(之前我自己折腾过)要把一堆 PDF 灌进去做问答;RAGFlow(写过)要从一堆 .docx 里抽出实体;甚至我日常让 Claude Code 读一份报表、写一段周报 —— 只要文件不是 .md、.txt,几乎就要打回到一个” 先做格式转换” 的死循环里

这个死循环的本质,是市场上的” 文档转 Markdown” 工具高度碎片化。

让我把主流几个拉出来排个队:

工具 支持格式 输出质量 速度 维护状态
Pandoc 5/14 表格糟糕,中文乱码 102 ms 学术老牌,但 LLM 时代不太跟得上
MarkItDown 6/14 一般 135 ms Microsoft 出品,Python 生态友好
Mammoth 1/14(仅 docx) docx 不错 53 ms 仅 Word 文档干净,其他靠边站
Docling 4/14 中等 514 ms IBM 出品,偏 PDF 解析
Unstructured 8/14 中等 573 ms 很完整,但 Python 包巨大,部署慢
LibreOffice Headless 12/14 表格惨烈 1129 ms 通用,但需要 1GB+ 系统依赖,慢得离谱
anydoc 14/14 81 分 4.4 ms Firecrawl 出品

这个对比表不是我拍的 —— 直接从 anydoc 的 README 里扒出来,用 Claude Sonnet 5 当裁判盲评出来的。后面的章节我会贴完整 benchmark。

回到问题:为什么这个市场这么久没人一统?

我观察到的三个根因:

  • 格式多到不可思议。 我们日常打交道 14 种格式:Word 三代(.doc/.docx/.docm)、PPT 三代、Excel 三代、OpenDocument 三兄弟(.odt/.ods/.odp)、RTF、EPUB、CSV、PDF。每种格式的内部结构差别极大,Word 是 OOXML XML 流,PPT 是压缩包里的 XML + 媒体文件,老 .doc 还是 OLE 二进制复合文档。维护 14 套解析器的工程量,谁做谁都头大。
  • 每个项目只解决自己关心的格式。 Mammoth 只做 docx,因为它假设你只用 Word 写文章;Pandoc 通吃但侧重学术 Markdown,对 Word 表格不友好;Unstructured 想做企业级但 Python 包臃肿到 200MB+;Docling 偏 IBM 企业自家 PDF 流程…… 没有人想要” 一份代码吞下 14 种格式”。
  • 输出标准不统一。 即使某一天你把 5 个工具拼起来,Pandoc 转的表格、MarkItDown 转的标题、Mammoth 转的列表,三者放在一起风格完全不同 —— 你还要写一层” 格式归一化”。这一层活儿比解析还累。

Firecrawl 团队看到这个痛点,是因为他们自己业务就被它扎到。从 firecrawl.dev 的主页可以看到,他们的核心产品 Firecrawl 就是” 把任何网页爬成干净 Markdown 给 LLM 用”—— 但当客户开始把爬下来的内容跟内部 Word、PPT、Excel 混在一起喂给 AI 的时候,” 网页→Markdown” 这一步远远不够

所以 anydoc 一句话的定位:

Fast Rust library that converts documents (Word, PowerPoint, Excel, OpenDocument, RTF, EPUB, CSV, and PDF) into clean GitHub-Flavored Markdown.

加上 README 后面那句更狠:

Built by Firecrawl to turn any office document into LLM-ready Markdown in single-digit milliseconds, with one consistent output no matter which format goes in.

——single-digit millisecondsone consistent output

这两个承诺要是真做到了,就不是又一个” 工具” 的问题,是重新定义了” 文档→LLM” 这条管线的基础设施


二、核心功能:把 14 种格式卷成一份 Markdown

先上一张官方格式矩阵,看看 anydoc 到底覆盖了什么。

1. 14 种格式全支持

类别 扩展名
Word .doc .docx .docm
PowerPoint .ppt .pps .pot .pptx .pptm .ppsx .ppsm
Excel .xls .xlsx .xlsm .xlsb
OpenDocument .odt .ods .odp
RTF .rtf
EPUB .epub
CSV .csv
PDF .pdf

14 种,0 缺漏。注意几个细节:

  • Word 三代全覆盖 —— 这意味着即使用户给你一份来自 2003 年的 .doc 文件(很多政府、金融机构的存量文档还是 .doc),你也能拿到干净输出。绝大多数现代工具只会做 .docx。
  • PPT 八个变体 ——.ppt/.pps/.pot/.pptx/.pptm/.ppsx/.ppsm,原始 .ppt OLE 流都吃。这种覆盖度在开源工具里几乎是第一次见。
  • Excel 含 .xlsb—— 很多企业系统导出的是二进制 Excel(.xlsb),Unstructured 之前都不认它,anydoc 收。
  • OpenDocument 三件套 ——LibreOffice 系用户的核心格式,Pandoc 对 .ods 处理经常炸表格。
  • PDF 不靠 OCR—— 文本型 PDF 直接走 Firecrawl 自家的 pdf-inspector 解析引擎,不需要任何外部服务。扫描件 PDF 才需要配 OCR(这块下面聊局限时会说)。

2. 单一输出口径:所有格式 → 统一 Markdown

这一条是 anydoc 真正的” 杀手锏”—— 不是支持多少格式,而是所有格式出来的 Markdown 长得一模一样

README 里这张表挺有价值:

1
2
3
4
5
6
7
8
9
10
11
12
13
document bytes

├─► format detection → content markers, not the extension

├─► format parser → one per format (doc, docx, ppt, pptx, xls,
│ xlsx, odt/ods/odp, rtf, epub, csv)
│ │
│ └─► Document → shared model: blocks, inlines, tables,
│ footnotes, assets
│ │
│ └─► GFM serializer → Markdown

└─► PDF → pdf-inspector → Markdown directly

所有非 PDF 格式都先解析到同一个 Document 模型,再交给唯一的 GFM serializer 序列化

这意味着什么呢?我举一个我自己的实际例子。

我之前用 Pandoc 转一份 .docx 表格,结果表格里带有特殊符号的单元格被错误转义成了 \"。我换 Mammoth 再转一份发现,单元格被直接 & 编码成了 HTML 实体。第三次试 Docling,表格居然没识别出来,行数和列数都被错位合并了。

—— 同一个表格,三个工具三套输出。

如果用 anydoc,因为所有 14 种格式都流经同一个 Document 模型 + 同一个 serializer,escape 规则、表格规则、标题规则、footnote 规则只实现一次,所有格式都受益。这就是 README 那句很优雅的设计描述:

Because every format funnels through the same document model and serializer, output quirks get fixed once. A table-escaping fix for docx is automatically a table-escaping fix for rtf, odt, and everything else.

—— 一处修,处处修。

文档输出还把” 完整结构” 做到一种执拗的程度:

  • 标题:带 anchor
  • 强调:bold / italic / strikethrough
  • 代码:inline code + fenced code blocks
  • 链接:外链 + 内部交叉引用
  • 列表:bullet /numbered/ 嵌套 /task list,带原始编号
  • 表格:合并单元格、表头行识别
  • 引用:block quote
  • 脚注:footnotes + endnotes
  • 演讲者备注:speaker notes(PPT 专属)

每一条都不是花活儿,是 LLM 真正需要消费的语义层。我之前喂 Claude Code 写周报,最痛的就是表格里中文标点全乱了;anydoc 表格的 escape 走统一路径,就不会出现这个。

3. 嵌入资源:图片和媒体被” 妥善挂载”

文档转 Markdown 最容易被忽略的是嵌入资源 ——Word 里的图、PPT 里的图表、PDF 里的 logo。

anydoc 的处理方式很克制:

  • 有外部 URL 的图片:直接渲染成 Markdown image
  • 嵌入二进制资源:渲染成 alt text,原始字节可从 Document.assets 取回,附带 media type

这点不像 Unstructured 那样直接把整张图 base64 嵌进去 ——anydoc 默认输出的 Markdown 是”LLM 友好的”,不会让图片巨幅污染上下文窗口,但如果你真的需要图,结构化 API 仍然能拿。

4. 内容签名识别:扩展名错也不怕

这是我特别喜欢的一条设计 —— 格式识别不靠扩展名,靠文件内容签名

1
2
3
Format::from_bytes(&bytes); // Some(Format::Docx), or None when nothing matches
Format::from_extension("pptm"); // Some(Format::Pptx)
Format::from_path(Path::new("report.odt")); // Some(Format::Odt)

识别器认的标准签名包括:

  • PDF 文件头 %PDF-
  • RTF 的开放组 {\rtf
  • OLE 复合文档的 stream 名
  • ZIP 包里的 [Content_Types].xml mimetype
  • EPUB 的 mimetype 文件

CSV 没有标准签名,所以仍然需要显式指名。但除此之外,前面那些格式 ——“被命名错的 .pdf”、” 扩展名是 .txt 但其实是 docx”—— 都能被正确识别。

我觉得这点在中国场景特别有用:你下载的论文、报告、政府公文,扩展名经常是乱起的;客户给你发的 .dat 包里塞的 .docx 是常见操作。

5. Agent Skill 装好就能用:npx skills add firecrawl/anydoc

这里我得特别说一点 ——anydoc 不是” 又一个工具库”,它把自己定位成 Agent 时代的一等公民

它上线第一天就发布了一个 Agent Skill(Claude Code / Codex / Cursor / OpenCode 等所有 agentskills.io 兼容客户端都吃):

1
npx skills add firecrawl/anydoc

装好之后你跟 Claude Code 说:

“把~/Downloads/2025 报告 一并 Markdown,存到~/notes/“

Claude Code 会自己调用 anydoc 把那一坨 .docx/.pptx/.pdf 全转了。

我装下来试了几次,最大的体验是 —— 不再需要为每种文档写一个 Tool 的 schema。一个 anydoc 处理 14 种格式,Claude Code 一个工具调用搞定。这种” 工具即基础设施” 的姿态,是 anydoc 比 Docling/Unstructured 更现代的地方。

6. WASM 版:浏览器本地转换,文件不出本机

README 一上来就挂了个 demo:

Try it in your browser: the demo page runs the library as WebAssembly, so files are converted locally and never leave your machine.

—— 这是隐私敏感场景的福音。

我之前研究过几个” 前端 PDF 转 Markdown” 的工具,要么慢要么不准,要么把文件上云。anydoc 的 WASM 版直接让浏览器跑 Rust 内核,零延迟、零数据外发。装包就一行:

1
npm install @firecrawl/anydoc-wasm
1
2
3
4
import init, { toMarkdownBytes, toDocument } from '@firecrawl/anydoc-wasm';

await init();
const markdown = toMarkdownBytes(bytes); // 文件不离开浏览器

对企业内 SaaS、需要合规审计” 数据不能出客户浏览器” 的场景,WASM 版是个杀手特性。


三、技术架构亮点:不是单纯快,是” 快 + 准 + 稳” 三件事一起做

我把仓库扒了一遍,觉得 anydoc 的工程细节藏得很深,但每一个都指向” 我们是认真在做这件事的”。挑几个最值得说的讲。

1. 速度是真的快:4.4ms 中位数

任何扯” 快” 的项目我都先看 benchmark。anydoc 这个 benchmark 是用 Claude Sonnet 5 当裁判盲评出来的 —— 不像别家用” 字符串相似度” 那种不可靠指标。

100 篇真实世界文档,14 种格式,482 次两两对比裁决(每个对比两次对调位置消除偏差)。

工具 支持格式 中位耗时 LLM 裁判总分
anydoc 14/14 4.4 ms 81
LibreOffice 12/14 1129.5 ms 40
MarkItDown 6/14 134.8 ms 65
Unstructured 8/14 572.9 ms 63
Pandoc 5/14 102.1 ms 56
Docling 4/14 513.6 ms 57
Mammoth 1/14(仅 docx) 52.5 ms 70

几个关键观察:

  • 4.4 ms vs 1129 ms—— 比 LibreOffice 快 256 倍。这是 no-brainer 式的差距。
  • 比 MarkItDown 快 30 倍,但格式覆盖是它的 2.3 倍,输出质量还比它高 16 分。
  • 唯一覆盖 14/14 格式的工具
  • 每一个 it 支持的格式,质量都高于或显著高于竞品 —— 下面那张按格式的细分表能看出。

按格式拆开看:

格式 anydoc LibreOffice MarkItDown Mammoth
.doc 87 57 - -
.docx 88 56 71 70
.pptx 74 24 66 -
.xlsx 72 30 55 -
.pdf (走 pdf-inspector) - - -
.odt 80 51 - -
.rtf 88 53 - -
.epub 77 - 72 -

anydoc 在每个有裁判的格式上都是第一名。这不是” 自家说自己好”,是 Sonnet 5 盲评的结论。

benchmark 是怎么跑的?anydoc 团队在 bench/ 里详细描述了:

  • 数据集:14 种格式的 100 篇真实文档(不公开)
  • 评分模型:Claude Sonnet 5
  • 评分流程:每对工具的输出对比地面真相(LibreOffice 把每个文档前 6 页渲成图),对 completeness /structure/formatting /cleanliness 四个维度独立打分
  • 偏差控制:每对对比都做两次(输出顺序对调),合计 482 次裁决
  • 速度测试:每篇文档一次 warm conversion,Ryzen 9 9950X3D + 64GB DDR5-6400 + Windows 11

这套 benchmark 方法论比” 我跑了个 hello world 看 ms” 严谨得多,可以直接拿到自己项目里照抄。

2. 单一 Document Model 是工程级的” 统一战争”

前面反复提” 所有格式解析到同一个 Document,再序列化”。这个东西工程上比听起来难做得多 —— 不同格式的语义差别巨大,怎么抽象出一个” 通用表示”?

我扒了仓库结构,结合 README 的”How it works” 那段,反推出他们大致是这么做的:

  • 每个格式(doc /docx/ppt /pptx/xls /xlsx/odt /ods/odp /rtf/epub /csv)一个 parser。
  • 每个 parser 的任务只有一件:” 把字节流变成 Document“—— 一份由 blocks(段落、列表、表格、引用、代码块)、inlines(粗体、斜体、链接、代码、脚注引用)、tables(带合并单元格和表头)、footnotes、assets 组成的结构化数据。
  • 唯一一个 GFM serializer 把 Document 拍扁成 Markdown。

这种” 中间表示 + 单一序列化” 的做法在编译器领域是 IR(中间表示)的标配(LLVM IR、MLIR 都这套)。放在文档转换上是相对新的尝试 —— 之前 MarkItDown、Unstructured 都是每个格式各写一套 Markdown 拼装。

代价是什么?Document Model 的字段必须足够丰富,得能装下所有格式的怪癖。比如 PPT 的 speaker notes、EPUB 的章节层级、Word 的脚注 + endnote、Excel 的合并单元格 + 表头识别、ODF 的 OLE 对象…… 都得有对应字段。这个抽象层 anydoc 写了一年多,PR 数比正常 parser 工作量大得多。

但收益也很明显:escape、表格、heading、footnote 这几个最坑的” 输出差异点” 只实现一次。这比” 再写一遍” 可靠得多。

3. 内容签名检测:防止扩展名错乱

格式识别这一段我专门读了代码逻辑(虽然没全读完),关键点是它绝不靠扩展名

格式类型 签名方式
PDF 文件头 %PDF-
RTF 开放组 {\rtf
OLE 复合(旧 .doc/.xls/.ppt) Stream 名(如 WordDocumentWorkbook
ZIP 包(docx/xlsx/pptx/odf/epub) [Content_Types].xml mimetype / EPUB 的 mimetype 文件
CSV 无标准签名 → 显式指定

这个设计在企业场景救命:

  • CRM 后台导出的 .dat 里塞的是 .docx,文件名和扩展名都对不上
  • 客户用邮件发的附件经常被中间系统改扩展名
  • 政府 / 事业单位的 PDF 经常被误命名为 .htm

anydoc 全能正确识别。中国场景下这点特别重要 —— 我见过太多” 文件名是 .doc 但其实是 wps 二进制” 的产物。

4. 错误模型:清晰且” 工程友好”

1
2
3
4
5
6
7
8
match anydoc::to_markdown(path) {
Ok(markdown) => Some(markdown),
Err(error @ (ConvertError::Encrypted | ConvertError::Unsupported(_))) => {
unconverted.push((path, error));
None
}
Err(error) => return Err(error),
}

错误类型只有六种:

Variant 含义
Unsupported 未知格式,或无法转换(图版 PDF)
Malformed 结构不可用,没法抠出有意义内容
Encrypted 加密或密码保护
ResourceLimit 超安全限制(解压、嵌套、节点数)
MissingPart 必要部件缺失
Io 文件读取失败(仅 to_markdown

这种” 重型业务错误分类型” 的做法是 Rust 圈的好习惯 ——Io 之外的错误都意味着” 这份文档救不回来”,上层可以决定” 丢弃 + 日志” 还是” 丢人工审查”。

对国内做 RAG 的工程师来说,这等于内置了一套” 哪些文档该跳过” 的判定逻辑,不用再去对每种格式写” 文档解析失败咋办” 的 workaround。

5. 测试体系:mutation test + cargo-fuzz + benchmark

仓库里现在已经有这些测试基础设施:

  • tests/fixtures/——committed 的回归样本,snapshot 测试
  • tests/robustness.rs—— 对每个 fixture 做 mutation testing(改一两个字节,看解析器会不会爆掉)
  • fuzz/——cargo-fuzz 目标覆盖每个格式
  • bench/—— 可复现的 quality + speed benchmark

Mutation test 这件事在文档解析器里几乎是奢侈品 —— 绝大多数 MarkItDown、Unstructured 都没有。Firecrawl 团队把这套流程做出来,本质上是在说:” 我们要维护的不是一次性 demo,是基础设施级别的库。”

6. 性能细节:为什么能这么快

不展开讲代码(篇幅所限),但几个工程细节值得一提:

  • 纯 Rust,零 ML 模型:除 PDF 走自家 pdf-inspector 外,整套转换是 deterministic 的 deterministic parser,不调任何 LLM。
  • Node.js 绑定走 libuv thread pool:不阻塞事件循环,Node 服务可以高并发。
  • Python 绑定释放 GIL:转换过程中其他线程能继续跑,配合 asyncio 用没问题。
  • 并行转换多文档:因为格式独立、安全、无共享状态,多文档批处理近乎线性扩展。
  • WASM 浏览器跑:Firecrawl 站点上的 demo 直接把整个 Rust 内核编成 WebAssembly,无服务端参与。

按 Firecrawl 自己的描述:

“No ML models, no external services. Median conversion time is under 5ms per document.”

“Under 5ms” 是个营销数字。我跑了几份真实合同下来的体感是 ——5ms 是中位数,最大文件大概几十 ms。对比 Pandoc 启动 + 转换 + 退出要 100ms+、LibreOffice 启动一次 1.5s+,根本不是同一量级的工具。


四、怎么用:四套绑定开箱即用

下面这部分我会把 README 里最常用的几种姿势列出来,节省你直接试错的时间。

1. CLI(最快上手)

1
2
3
npx @firecrawl/anydoc report.docx               # Markdown to stdout
npx @firecrawl/anydoc slides.pptx -o slides.md # 或写到文件
npx @firecrawl/anydoc - --format csv < data.csv # 从 stdin 读

npx 会在第一次跑的时候下载对应平台的预编译二进制。想长期用,安装全局:

1
2
npm install -g @firecrawl/anydoc
anydoc --help

CLI 工具的好处是 —— 你能直接拿来当 shell pipeline 的一部分

1
2
3
4
# 把下载目录里所有文档批量转 markdown
for f in ~/Downloads/*.docx ~/Downloads/*.pptx ~/Downloads/*.pdf; do
anydoc "$f" -o "${f%.*}.md"
done

2. Python(pip 一行装)

1
pip install firecrawl-anydoc
1
2
3
4
5
6
7
8
9
10
11
12
13
import anydoc

# 从文件路径
markdown = anydoc.to_markdown("report.docx")

# 从字节(自动检测格式)
markdown = anydoc.to_markdown_bytes(data)

# 字节 + 显式格式(用于 CSV 这种没签名的)
markdown = anydoc.to_markdown_bytes(data, "csv")

# 拿原始 Document 模型(带 assets, footnotes, ...)
document = anydoc.to_document(data)

对我这种” 笔记 + RAG 都用 Python” 的人来说,是最高频的入口。我打算把 anydoc 接到我自己的 Open Notebook 流程里 —— 替换之前那一坨 mammoth + pdfplumber 拼凑的代码。

3. Node.js(也是 npm 一行)

1
npm install @firecrawl/anydoc
1
2
3
4
5
6
import { toDocument, toMarkdown, toMarkdownBytes } from '@firecrawl/anydoc';

const markdown = await toMarkdown('report.docx');
const fromBytes = await toMarkdownBytes(bytes); // 自动检测
const fromCsv = await toMarkdownBytes(bytes, 'csv'); // 显式指名
const document = await toDocument(bytes); // 拿 Document 模型

4. Rust(cargo 一行)

1
2
3
# Cargo.toml
[dependencies]
anydoc = "0.1"
1
2
3
4
let markdown = anydoc::to_markdown("report.docx")?;
let markdown = anydoc::to_markdown_bytes(&bytes, None)?;
let markdown = anydoc::to_markdown_bytes(&bytes, anydoc::Format::Csv)?;
let document = anydoc::to_document(&bytes, None)?;

Rust 入口主要给” 想做 deeper integration 的基础设施团队” 用 —— 比如你公司要做一个内部” 文档中台”,直接 cargo add 进来做底层引擎。

5. Agent Skill(让 Claude Code / Codex 直接用)

这是我用得最多的方式:

1
npx skills add firecrawl/anydoc

装完之后 Claude Code / Cursor / Codex 都会自动识别这个技能。当你说” 把这份文档转成 markdown” 或” 读一下这份 PPT”,Agent 会自己调用:

  • anydoc convert <file>
  • 拿到输出文本
  • 接着做你要的事

实测下来很顺。我之前用 Claude Code 读一份 .pptx 走 LibreOffice headless,每次要花 10s+ 启动进程;现在 anydoc 4.4ms,体感完全不一样。

6. WASM 浏览器(合规场景)

1
2
3
4
import init, { toMarkdownBytes, toDocument } from '@firecrawl/anydoc-wasm';

await init();
const markdown = toMarkdownBytes(bytes); // 数据全程不出浏览器

在线 demo 直接看效果 —— 拖个 .pdf/.docx 进去,本地转完直接在页面显示 Markdown。


五、适用人群 & 局限性

适合谁用

按我自己的判断,下面这些场景用 anydoc 都是躺赢:

  • RAG 数据预处理 —— 把企业内部 .docx/.pptx/.xlsx 一并塞到向量库。比 MarkItDown / Unstructured 干净一个量级。
  • AI Agent 工具链 —— 上面 Agent Skill 已经讲了。Claude Code / Codex / Cursor 都能直接用。
  • 个人笔记 / Obsidian / Logseq 工作流 —— 把 WPS 输出的 .doc 周报转 markdown 永久归档。
  • 合规型 SaaS——WASM 浏览器版让” 文件永远不出客户浏览器” 成立。
  • 学术 / 论文场景 ——EPUB + PDF 都是强项,Pandoc 现在反而成为兜底。
  • 企业内部文档中台 ——Rust 库直接 cargo add,做高吞吐量文档解析。

局限性(写博客不藏着掖着)

也不是没短板,简单列一下我从仓库和 benchmark 里看到的局限

  1. 图版 PDF 需要外部 OCR—— 文本型 PDF 走 pdf-inspector 没问题,扫描件 / 图版 PDF 要配 OCR。anydoc 这块的设计建议是接 Firecrawl 自家的云 OCR 服务(或自己接 PaddleOCR、Tesseract)。文本型 PDF 和扫描件需要按场景分流。
  2. 超大文件处理 —— 标准 .pdf 没什么问题,几百 MB 的 PDF 要考虑一次性转换还是流式。anydoc 的 ResourceLimit 错误类型有一个安全上限(解压 / 嵌套 / 节点数)。
  3. 加密文档 —— 明确报 ConvertError::Encrypted,需要密码的 PDF/Win Word 文档不能处理。这跟设计假设一致。
  4. 速度 vs Pandoc 那种轻量 —— 如果只是要把一份 .md 转成 .docx,Pandoc 的 102ms 仍是合理选择。anydoc 的 4.4ms 在大文件批处理上才显示出绝对优势,单个小文件差距会被 npx 下载开销 cover。
  5. 比较新,生态还在建 ——0.1.x 版本,15 天 16.7k stars 这种爆发期,issues 72 个开放中。生产用建议先 small-scale pilot,等 0.2/0.3 再加大用。
  6. 绑定的同步性 ——Node/Python/WASM 三套绑定的版本号会稍微落后于 Rust core。仓库里靠 .github/workflows/release.yml 一起 bump 三处版本,但偶尔会有 1~2 周偏差。

但这些局限跟” 它解决的问题” 比起来,都是工程上可以 manage 的程度。


总结:把” 文档→Markdown” 卷到尽头

firecrawl/anydoc 这个项目我最欣赏的一点,是它没有去卷”AI 加持”—— 你没有看到它说” 我们用 LLM 智能转换”、没有看到它把解析丢给 GPT。它就是纯 Rust、deterministic、单 IR + 单 serializer、确定性结果。

这件事本身就很 refreshing。

它的全部赌注是:文档格式多但语义收敛。只要把 14 种格式的解析都收敛到同一个 Document Model,再做一个稳的 GFM serializer,剩下的就是工程问题 —— 速度、benchmark、测试、绑定

而这些恰好是 Firecrawl 这个团队最擅长的事。

Firecrawl 团队的判断是:Web 已经是 Markdown,云端文档也该是 Markdown,办公文档更该是 Markdown。anydoc 把最后一块拼图补上 —— 从此,Agent 读什么格式都一样

如果你是 AI 应用开发者、RAG 工程师、Agent builder、企业知识库产品经理,这 20 分钟花得值 ——

1
2
3
4
5
pip install firecrawl-anydoc
# 或
npm install @firecrawl/anydoc
# 或
npx skills add firecrawl/anydoc

你大概率会跟我一样,回来感叹一句:” 原来这些年我的文档管线都白写了。”


🔗 GitHub 地址github.com/firecrawl/anydoc(16.7k stars · MIT · Rust + Node.js + Python + WASM)

如果你也在做 RAG / Agent / 企业知识库,欢迎留言告诉我你日常文档管线是用什么搭的 —— 我现在彻底把 MarkItDown + Pandoc + mammoth 全替换了。

—— 戴老板,写于杭州・办公室