2026/8/15 10:45:23

anydoc:把 Word/PPT/PDF 变成干净 Markdown 的开源神器,RAG 数据管道的刚需

anydoc:把 Word/PPT/PDF 变成干净 Markdown 的开源神器,RAG 数据管道的刚需 摘要:RAG 的检索质量,一半取决于喂给它的文档被解析得干不干净。Firecrawl 开源的anydoc用 Rust 把 Word/PPT/Excel/PDF 等 14 种格式统一转成干净、结构完整的 GitHub-Flavored Markdown,上线 9 天 GitHub 星标已超 1.4 万。本文拆解它解决了什么痛点、实测安装与转换质量,并和 Unstructured、MarkItDown、Docling 等主流方案做了选型对比。一、痛点:企业文档进 RAG,为什么第一步就卡壳做 RAG 的开发者大多有同一种经历:文档解析的代码写得比检索逻辑还久。企业知识库里是成堆的.docx、.pptx、.xlsx、.pdf,它们在进 LLM 之前必须先变成干净文本,而这一步处处是坑:PDF 是重灾区。很多 PDF 没有可靠的文本层,排版靠坐标定位,表格、页眉页脚、多栏混在一起;扫描件还要 OCR。传统 PyPDF 类库提取出来的往往是一坨断行纯文本,标题层级、列表结构全丢。Office 格式的隐性结构多。Word 里的表格、批注、脚注,PPT 里的演讲者备注,Excel 里的合并单元格——这些结构对人读有意义,对模型读更有意义(检索时一个表头就是一条黄金索引),但多数解析器要么丢掉,要么渲染成标签噪音。格式越杂,管道越脏。真实企业语料是多种格式混存的,每种格式配一个解析方案,输出风格还不统一:有的带 HTML 标签、有的纯文本、有的 Markdown 半成品。下游分块(chunking)和 embedding 得为每种输出写特判,维护成本极高。一句话:解析器的输出质量,直接决定检索质量;而多数 RAG 管道的第一公里,是拿最糙的工具在跑。anydoc 正是冲着这个环节来的。二、anydoc 是什么:一个 Rust 库,统一 14 种格式anydoc 是网页抓取/解析服务商Firecrawl开源的项目,定位一句话就能说清:“把 Word、PowerPoint、Excel、OpenDocument、RTF、EPUB、CSV 和 PDF 转成干净的 GitHub-Flavored Markdown,内置 Node.js / Python / 浏览器(WebAssembly)绑定。”仓库firecrawl/anydoc创建于 2026-08-03,语言 Rust,协议 MIT。截至 2026-08-12 实测:GitHub 星标 14,390、fork 753,发布 9 天即破 1.4 万星;npm 包firecrawl/anydoc、PyPI 包firecrawl-anydoc、crates.io 的anydoc均已发布到 v0.1.8(2026-08-12 实时查询)。支持格式(官方 README 清单):格式扩展名Word.doc.docx.docmPowerPoint.ppt.pps.pot.pptx.pptm.ppsx.ppsmExcel.xls.xlsx.xlsm.xlsbOpenDocument.odt.ods.odpRTF / EPUB / CSV / PDF.rtf.epub.csv.pdf设计上几个关键点值得注意:统一文档模型 单一序列化器。每种格式先解析进同一个Document模型(块、行内、表格、脚注、资源),再走同一个 Markdown 序列化器。docx 上修好的表格转义 bug,rtf/odt 自动一起修好,输出风格天然一致。按内容识别格式,不信任扩展名。格式从文件字节判断(PDF 头、RTF 分组、OLE 流名、ZIP 包 mimetype),扩展名乱标也能转对;CSV 没有文件签名,需要显式指定。嵌入资源保留。图片渲染为 alt 文本,原始字节仍挂在文档模型上、带媒体类型——需要图片时不必重跑一遍解析。专为 Agent 设计。官方把它打包成 Agent Skill,npx skills add firecrawl/anydoc之后,Claude Code / Codex / Cursor 等 Agent 就能直接读取办公文档。另外值得一提的是一套明确的错误模型。转换失败时,库返回的不是笼统的解析失败,而是带语义的ConvertError:Encrypted(加密/密码保护)、Unsupported(未知格式或纯图片 PDF)、Malformed(结构损坏)、ResourceLimit(超过解压/嵌套/节点数安全上限)、MissingPart(缺少必要部件)。对批量管道来说,这意味着可以精确分流:加密文件单独登记、损坏文件跳过、未知格式报警,而不是把整批任务交给try/catch碰运气。Node 和 WASM 绑定把变体名放在error.code,Python 则每种变体对应一个异常子类。三、上手实测:安装、用法与转换质量3.1 安装与命令行官方 CLI 用法(已在本机实测,npm 会自动下载对应平台的预编译二进制):# 一次性使用(输出到 stdout)npx firecrawl/anydoc report.docx# 输出到文件npx firecrawl/anydoc slides.pptx-oslides.md# 从 stdin 读取,指定格式(CSV 无文件签名,必须显式指定)npx firecrawl/anydoc ---formatcsvdata.csv# 永久安装npminstall-gfirecrawl/anydoc3.2 三种语言绑定官方 README 提供的 Node.js / Python / Rust 调用方式(均已核对官方文档):// Node.jsimport{toMarkdown,toMarkdownBytes,toDocument}fromfirecrawl/anydoc;constmdawaittoMarkdown(report.docx);// 从路径constmd2awaittoMarkdownBytes(bytes,csv);// 从字节,显式指定格式constdocawaittoDocument(bytes);// 停在文档模型,可取嵌入资源# Pythonimportanydoc mdanydoc.to_markdown(report.docx)md2anydoc.to_markdown_bytes(data,csv)docanydoc.to_document(data)// Rustletmdanydoc::to_markdown(report.docx)?;letmd2anydoc::to_markdown_bytes(bytes,anydoc::Format::Csv)?;letdocanydoc::to_document(bytes,None)?;// 停在文档模型,可取嵌入资源3.3 转换质量实测(本机真实运行)为了不纸上谈兵,我在本机用 v0.1.8 CLI 逐个转换了 CSV、带合并单元格的 XLSX、真实 Word 表格 docx 和文本型 PDF:CSV → Markdown 表格(标准 GFM 表格,表头自动识别):| name | age | city | | --- | --- | --- | | Alice | 30 | Beijing | | Bob | 25 | Shanghai |带合并单元格的 XLSX → Markdown 表格(合并内容保留,GFM 无原生合并语法,跨列以空单元格呈现):| | | | | --- | --- | --- | | Merged across | | padded | | tall | b2 | 3.5 | | | b3 | |真实 Word 表格 docx → Markdown(标题、表格、列表全部还原):# 季度营收报告 这是正文段落,包含一些说明文字。 | 产品 | Q1 营收 | Q2 营收 | | --- | --- | --- | | A 产品 | 100 万 | 120 万 | | B 产品 | 80 万 | 95 万 | 要点列表: - 第一点 - 第二点文本型 PDF → Markdown:标题层级、加粗/斜体/删除线、嵌套有序列表、脚注、内外部链接均完整保留;README 功能清单还覆盖代码块、任务列表、演讲者备注等结构(本次 fixture 未逐一验证)。需要说明的边界:anydoc 本地只处理文本型 PDF,扫描件/图片型 PDF 需要走 Firecrawl Parse 托管 API 的 OCR(官方 README 明确写了这一点)。另外,我实测的 PDF fixture 中表格以文本行呈现,未还原为管线表格——PDF 表格保真度取决于源文件的排版结构,选型时对扫描件为主的语料要有预期。速度方面,官方自测口径是单文档中位转换 4.4 ms(纯 Rust、无 ML 模型、无外部服务);我在本机连续转换 CSV/DOCX/XLSX/PDF 的体感是毫秒级、几乎无感,与自测方向一致。对每天要灌几万份文档的批处理管道来说,解析不再是瓶颈。3.4 与 Firecrawl 生态联动anydoc 不是孤立工具:它本身就是Firecrawl Parse(firecrawl.dev/parse,托管解析 API)的底层引擎。不想自建管道时,直接调 Parse API 拿到同样的转换结果,外加 OCR 能力;想在浏览器里零安装体验,官方还有 WebAssembly 演示页(文件只在本地转换,不上传)。开源自建 托管兜底,两条路都给你留好了。对大多数团队,一个务实的组合是:日常批量转换用本地 anydoc(免费、快、数据不出内网),遇到扫描件/超复杂版面再单独送 Parse 的 OCR 兜底——既控成本,又不让长尾 PDF 卡住整条管道。四、选型对比:与 Unstructured / MarkItDown / Docling 怎么选官方 README 给了一份自测 benchmark:用 100 份真实文档(覆盖 14 种格式)、以 LibreOffice 渲染前六页为基准,让 LLM 盲评(Claude Sonnet 5,双盲交换 482 次判定),对比 anydoc 与六个主流转换器。核心结果:工具覆盖格式中位耗时综合分anydoc14/144.4 ms81markitdown6/14134.8 ms65unstructured8/14572.9 ms63docling4/14513.6 ms57pandoc5/14102.1 ms56libreoffice12/141129.5 ms40mammoth1/1452.5 ms70注意口径:这是项目方自测、且各工具综合分覆盖的格式集合不同(mammoth 的 70 只算 docx 一种,anydoc 的 81 是 14 种格式平均),只能当参考,不能当权威横评。但结合我的实测,几个结论是站得住的:格式覆盖最全:14 种全支持,是表格里唯一一份代码吃下所有办公格式的;Unstructured 主打 PDFOffice,MarkItDown 偏 Web 场景,Docling 强在 PDF 但 Office 覆盖少。速度是数量级优势:中位 4.4 ms,比第二名 MarkItDown 快约 30 倍,比 LibreOffice 转换(1.1 秒级)快两个数量级。输出统一:所有格式走同一序列化器,下游分块逻辑只需写一遍——这恰恰是 RAG 管道最容易被忽略的隐性成本。纯 PDF 方案不在对比表里:PyMuPDF / Marker 等对付复杂排版 PDF OCR仍是强项,anydoc 的短板也正在 PDF(文本型本地解析、扫描件走托管 OCR)。如果你的语料 90% 是扫描 PDF,选 Marker 类方案更对口;如果是一堆 docx/pptx/xlsx 少量文本 PDF 的混合办公语料,anydoc 是更省事的默认项。落到何时用 anydoc的决策上,我的判断是:只要你的语料里 Office 格式占比超过两成、或格式类型超过三种,anydoc 就值得作为默认解析器进管道。原因不是单一 benchmark 分数,而是工程上的三个省:省掉多套解析器的集成成本、省掉为各格式输出写特判的分块逻辑、省掉几万文档批处理时的等待时间。反之,若你的场景是单一格式、海量扫描 PDF、强依赖版面分析,那 PDF 专用方案(或托管 OCR)仍是不可替代的;anydoc 更适合作为管道中的第一层通用解析器,与专用方案分层共存。五、总结anydoc(MIT,Rust,firecrawl/anydoc,上线 9 天 14,390 star)把 14 种办公/文档格式统一转成干净、结构完整的 GFM Markdown,输出风格一致,官方自测中位转换 4.4 ms,附带 Node.js / Python / Rust / WASM 四套绑定;实测确认:CSV / XLSX(合并单元格)/ 真实 Word 表格都能还原成标准 Markdown 表格,文本型 PDF 的标题、列表、脚注保留良好;边界是扫描件 PDF 需走 Firecrawl Parse 托管 OCR;选型上:混合办公文档为主、追求速度与输出统一的 RAG 管道,anydoc 是当前性价比最高的默认项;纯扫描 PDF 场景仍建议搭配 PDF 专用方案(如 Marker 或托管 OCR)。参考链接anydoc 仓库:https://github.com/firecrawl/anydoc官方 README(benchmark / 支持格式 / 绑定文档):https://github.com/firecrawl/anydoc#readmenpm 包 firecrawl/anydoc:https://www.npmjs.com/package/firecrawl/anydocPyPI 包 firecrawl-anydoc:https://pypi.org/project/firecrawl-anydoc/crates.io 包 anydoc:https://crates.io/crates/anydocFirecrawl Parse(托管 API):https://firecrawl.dev/parsepdf-inspector(anydoc 的 PDF 解析依赖):https://github.com/firecrawl/pdf-inspectorWebAssembly 浏览器演示:https://firecrawl.github.io/anydoc/