文档转Markdown,中位数4.4毫秒就够
你还在等LibreOffice转完一份docx再喂给模型吗?那份报告可能已经在队列里停了1秒多。anydoc直接把这件事压到中位数4.4毫秒,14种常见格式全覆盖,输出还是统一的GitHub风格Markdown。
它不是又一个“差不多能用”的转换器。Firecrawl用纯Rust重写了整条链路,把Word、PowerPoint、Excel、OpenDocument、RTF、EPUB、CSV、PDF都塞进同一个文档模型,再统一序列化。结果就是:不管你扔进去的是2003年的老.doc,还是昨天刚导出的.pptx,标题层级、合并单元格、脚注、任务列表出来都长得一样。本地跑,不调外部服务,也不需要机器学习模型。

很多人以为文档解析只能靠一堆工具拼起来,或者干脆上云。实际上本地就能做到这个速度和质量。它已经在给Firecrawl自己的Parse接口垫底,扫描版PDF才走额外的OCR。纯文本的PDF、办公文档,本地一把梭。
现有工具为什么总让人抓狂
你扔一份合同给模型,先要解决“它到底是什么格式”。后缀写着.docx,内容可能是被改过的ZIP;CSV更没标志,只能靠你手动指定。换工具就换一套输出规则,表格有时变成列表,脚注直接丢,嵌套列表层级乱掉。
LibreOffice中位数要1100多毫秒,还覆盖不到全部14种。unstructured、markitdown、pandoc各管一截,质量分数最高也就65左右。anydoc在同一批100份真实文档上跑出来的总分是81,完整度87,结构79,格式78,干净度81。速度差了大约250倍。
这不是实验室数字。500个docx压成1.7秒就能出完,直接能塞进agent循环里。以前你得先异步队列、再等回调,现在同步调用都觉得快。
我自己试过把一堆旧的.xls和.odp丢进去。有些文件名和真实格式对不上,它照样从文件头认出来。CSV这种没有特征的,你得显式告诉它“这是csv”,否则它就跳过。这种小细节挺有意思。
它怎么把速度和质量绑在一起
所有格式先走内容探测:PDF看文件头,RTF看分组,ZIP看mimetype。认出来之后进专用解析器,吐进统一的Document模型——块、行内、表格、脚注、嵌入资源都在里面。最后只走一条GitHub-Flavored Markdown序列化器。
所以表格合并单元格、标题锚点、删除线、代码块、演讲者备注,全部走同一套规则。图片和对象变成带alt的Markdown,原始字节还在模型里,需要的时候可以单独拿。
PDF走pdf-inspector,只处理带文本层的。纯扫描的它直接报Unsupported,不会假装读出来。加密文件也明确报错。这种诚实比“尽量转换”更省事。
纯Rust,没有Python解释器开销,没有临时文件落地。Node绑定走libuv线程池,不堵事件循环;Python释放GIL。中位数4.4毫秒就是这么来的。
有人觉得Rust写解析器会过度工程。也有人直接拿它当agent skill装上,让Claude或Cursor自己遇到文档就转。两种用法都有人在用。
真正上手只需要一行
CLI最直接:
npx @firecrawl/anydoc report.docx输出直接打到终端。想存文件就加-o slides.md。从标准输入读CSV的话:
npx @firecrawl/anydoc - --format csv < data.csvNode里:
import { toMarkdown, toMarkdownBytes } from '@firecrawl/anydoc';const md = await toMarkdown('report.docx');const mdFromBytes = await toMarkdownBytes(bytes);const mdCsv = await toMarkdownBytes(bytes, 'csv');Python差不多:
import anydocmd = anydoc.to_markdown("report.docx")md_bytes = anydoc.to_markdown_bytes(data)md_csv = anydoc.to_markdown_bytes(data, "csv")浏览器也能跑,装@firecrawl/anydoc-wasm,文件完全不离开本机。Rust直接cargo add anydoc。
agent场景更省事:npx skills add firecrawl/anydoc,之后工具链里遇到文档就会自动调用。
跑完你会看到干净的Markdown,表格、列表、标题都在。复杂文档偶尔会丢一点边角样式,那是解析器取舍,不是崩溃。
它还在0.1.x阶段。极端畸形文件、超大嵌入对象,理论上可能触发ResourceLimit。生产环境最好对返回的错误做分类处理:加密的、不支持的单独记下来,别让整个流水线挂掉。
本地能解决的就别再绕一圈云服务了。扫描件再交给带OCR的接口。速度和质量已经到这个位置,剩下的就是你怎么把它塞进自己的管道。
你那边批量转文档时,卡得最狠的是哪一步💬
如果你觉得这篇内容对你有启发,欢迎在留言区聊聊你的看法。
关注我,我会持续分享高质量的技术与思考干货。👇
夜雨聆风