乐于分享
好东西不私藏

Word、PPT、Excel 怎么统一转成 Markdown?我实测了 AnyDoc

Word、PPT、Excel 怎么统一转成 Markdown?我实测了 AnyDoc

Word、PowerPoint、Excel、EPUB、PDF,各有各的文件结构。想把它们统一转成 Markdown,往往要先适配多套转换工具。

AnyDoc 想解决的就是这件事:用一套 Rust 库接收多种办公文档,统一输出 GitHub 风格 Markdown。

我在 macOS arm64、Node.js 22.21.1 环境里,用 @firecrawl/anydoc 0.1.9 跑了仓库自带的 DOCX 样本。标题、表格、列表和嵌入对象提示都成功保留下来;换成普通 PNG 输入,它会明确返回 unsupported input,不会把图片当成文档,更不会自动做 OCR。

下面结合官方资料和本机复现,讲清它的结构、接入方式与使用边界。

01|AnyDoc 到底解决什么问题?

AnyDoc 是 Firecrawl 开源的一套文档转换库,核心使用 Rust 编写,当前版本为 0.1.9,采用 MIT License。

它支持八类文档家族:Word、PowerPoint、Excel、OpenDocument、RTF、EPUB、CSV 和 PDF,覆盖常见的 doc/docx、ppt/pptx、xls/xlsx、odt/ods/odp、rtf、epub、csv、pdf 扩展名。

它会尽量保留标题、链接、列表、表格、脚注、备注和嵌入资源等结构,再输出 GitHub-Flavored Markdown(GFM)。

官方浏览器 Demo 使用 WebAssembly 直接在页面内运行转换器。文件在浏览器本地处理,不需要上传服务器。下面这张图是官方 Demo 把 report.csv 转成 Markdown 表格后的真实页面。

AnyDoc 官方浏览器 Demo 的 Markdown 转换结果

**它适合“输入格式很杂,但下游只想接收一种文本结构”的任务。**例如内容迁移、文档预览、搜索索引和数据清洗。

02|为什么不同格式能得到相对一致的输出?

如果只看“支持八类格式”,很容易把 AnyDoc 理解成一堆转换脚本的集合。真正值得看的,是它在解析器和 Markdown 之间放了一层共享的 Document 模型。

官方 README 给出的处理链路可以概括成五步:

  1. 1. 读取文档字节。
  2. 2. 根据文件内容标记识别格式。
  3. 3. 交给对应格式的解析器。
  4. 4. 解析为共享的 Document 模型。
  5. 5. 通过同一套 GFM serializer 输出 Markdown。
AnyDoc 从文档字节到统一 Markdown 的处理链路

这里有两个设计点。

**第一个是优先按内容识别格式,而不是只信扩展名。**PDF、RTF 和 Office 文件都有对应内容标记;CSV 没有可靠签名,仍需扩展名或显式指定格式。

大多数格式共用中间模型和 serializer。解析器先把标题、段落、表格、脚注和资源收进 Document,再统一转成 Markdown。

这样做的直接收益,是输出规则不用按格式重复维护。官方举的例子很直观:修复一次表格转义,docx、rtf、odt 等格式都会一起受益。

PDF 是一个特殊分支。文本型 PDF 通过 pdf-inspector 直接生成 Markdown,不经过上面的共享 Document 路径。

AnyDoc 官方 README 中的解析架构说明

这套设计不能保证复杂文档百分之百还原,但能让下游少适配多套输出差异。

03|怎么接入:CLI、Node.js、Python 和浏览器

如果只想快速转换一个文件,CLI 最直接:

npx @firecrawl/anydoc report.docxnpx @firecrawl/anydoc slides.pptx -o slides.md

第一条输出到终端,第二条写入文件。首次执行时,npx 会下载预编译二进制。

Node.js、Python 和浏览器 WebAssembly 也有官方绑定。需要保留嵌入资源时,可以停在 Document 中间模型。具体吞吐仍要用自己的文档和并发模型验证。

04|本机跑一遍:成功路径和失败路径

我使用的验证环境是:

  • • macOS Darwin 25.5.0,arm64
  • • Node.js 22.21.1
  • • npm 10.9.4
  • • @firecrawl/anydoc 0.1.9

成功路径使用仓库里的 sample-rich.docx:

npx --yes @firecrawl/anydoc@0.1.9 sample-rich.docx

实际输出保留了标题、表格、列表和嵌入对象提示:

Quarterly Widgets| Quarter | Widgets || --- | --- || Q1 | 10 || Q2 | 14 |Embedded object: Excel.Sheet.12

失败路径直接传入一张普通 PNG:

anydoc: unsupported input:unrecognized file content and extension
AnyDoc 0.1.9 本机成功与失败路径验证

这个结果只证明:**在上述环境和样本上,DOCX 成功转换,普通 PNG 被正确拒绝。**它不能外推成“所有 Office 文档都能无损转换”,也不能说明 AnyDoc 具备图片识别能力。

05|官方 benchmark 很亮眼,但要看清口径

AnyDoc README 公布了一组项目方 benchmark:100 份真实文档、14 种格式,对比六种转换工具。

官方表格里,AnyDoc 覆盖 14/14 格式,中位转换时间为 4.4 ms,综合分为 81。

AnyDoc README 公布的官方 benchmark

这些数字可以帮助我们了解项目的设计目标,但不能直接当成独立选型结论,原因有三点:

  • • 数据由项目维护者提供,不是第三方测评。
  • • 质量分使用 LLM judge,对文档前六页的渲染图和转换结果进行比较。
  • • 测试语料不可再分发,没有包含在仓库中,我们无法原样复现整套质量比较。

所以更稳妥的读法是:官方 benchmark 说明 AnyDoc 在“多格式覆盖 + 低转换开销”上有明确目标,也给出了公开测试方法;真正接入前,仍要拿自己的复杂文档建立回归集。

06|边界在哪里,什么时候适合用?

最重要的边界是 OCR。

AnyDoc 可以本地处理文本型 PDF,但扫描页和纯图片 PDF 没有可提取文本,会返回 Unsupported。它不会调用模型,也不会自动把图片识别成文字。

如果不想自己运行,AnyDoc 也是 Firecrawl Parse 的底层转换组件。根据官方说明,托管 API 在相同转换能力之外增加了 OCR 模型,用来处理 AnyDoc 自身无法读取的扫描页面。

如果准备把它放进正式系统,我建议先做四项检查:

  1. 1. 输入是不是以 Office、EPUB、CSV 和文本型 PDF 为主?如果大量是扫描件,必须额外准备 OCR。
  2. 2. 是否需要本地、确定性的文档转换?如果是,纯 Rust、无外部服务是明显优势。
  3. 3. 是否依赖复杂表格、批注、特殊字体或嵌入对象?先用真实样本验证,不要只看简单 Demo。
  4. 4. 失败文件怎么处理?**至少记录错误类型、原始文件和重试策略,不要静默丢文档。

当前版本仍是 0.1.x。这不代表项目不能用,但意味着生产接入更应该依赖自己的回归测试,而不是只依赖 README 的示例和 benchmark。

07|结论:它是一层文档转换器,不需要被包装成别的东西

AnyDoc 的价值很具体:支持多种办公文档,用共享中间模型和一套 GFM serializer,把输入统一转换成结构化 Markdown。

需要 CLI、Node.js、Python、Rust 或浏览器本地转换时,它都提供了对应入口;需要扫描件 OCR 时,则要额外接识别服务,或者使用包含 OCR 的托管方案。

如果你准备试用,先选三份最复杂的真实文档:一份 Word、一份 PPT、一份 Excel。转换后重点检查标题层级、合并单元格、列表编号、脚注和嵌入对象,再决定是否进入正式流程。

你平时最难处理的是哪类文档:复杂 Word、PPT,还是 Excel?可以把具体结构说出来,我再用 AnyDoc 做一次针对性验证。

关于作者

我是老罗,一个持续学习和实践新技术的程序员。我会把学到的知识、做过的项目和踩过的坑,整理成真正能用起来的内容。

不止聊 AI,更想和你一起把 AI 用起来。