
AI 技能【免费下载链接】anydocConvert Word, PowerPoint, Excel, OpenDocument, RTF, EPUB, CSV, and PDF to clean Markdown. Built in Rust, with Node.js and Python bindings.项目地址https://gitcode.com/gh_mirrors/any/anydoc点击查看免费下载firecrawl-anydoc是 anydoc 这个 Rust 文档转换内核的官方 Python 绑定pip install firecrawl-anydoc之后你可以在 Python 里把 Word、PowerPoint、Excel、OpenDocument、RTF、EPUB、CSV 和 PDF 一次性转换为统一的 GitHub-Flavored Markdown。本文以 python/README.md 为主线结合绑定源码python/src/lib.rs、python/src/document.rs和测试python/tests/test_anydoc.py系统讲解安装、三种转换入口、异常体系、格式探测原理以及文档模型和嵌入资源的使用方式。安装与包名说明pip install firecrawl-anydoc一个容易踩坑的命名细节发行版PyPI 上的包名叫firecrawl-anydoc但导入名是anydoc因为 PyPI 上anydoc这个裸名已被无关包占用。这一点在 python/pyproject.toml 中有明确注释使用时请保持一致import anydoc包本身是一个通过 maturin 构建的 Rust 扩展见 python/pyproject.toml 的build-backend maturin模块名为anydoc._anydocPython 版本要求3.10。构建时启用了 pyo3 的abi3-py310特性python/Cargo.toml即每个平台只需一个 wheel 即可覆盖从 CPython 3.10 起的全部版本。类型支持开箱即用包内自带手写的类型桩文件 python/anydoc/_anydoc.pyi 和py.typed标记IDE 可以直接获得完整的类型提示测试 python/tests/test_anydoc.py 中test_the_stubs_cover_the_module还会解析桩文件与模块实际导出做差集校验确保两者不脱节。支持的格式格式扩展名Word.doc,.docx,.docmPowerPoint.ppt,.pps,.pot,.pptx,.pptm,.ppsx,.ppsmExcel.xls,.xlsx,.xlsm,.xlsbOpenDocument.odt,.ods,.odpRich Text Format.rtfEPUB.epubCSV.csvPDF.pdf注意表格里的一对多映射.docm、.docm等容器变体共享同一个解析器最终都归入基础格式。这一点在绑定层的FORMATS常量python/src/lib.rs中体现为 12 个规范格式名doc、docx、odt、pdf、ppt、pptx、rtf、epub、xlsx、ods、odp、csv也就是anydoc.Format这个Literal类型的取值python/anydoc/_anydoc.pyi。三种转换入口核心 API 是三个函数覆盖文件路径内存字节文档模型三种使用场景import anydoc # 1) 从文件路径转换格式由文件内容自动探测 markdown anydoc.to_markdown(report.docx) # 2) 从内存字节转换格式由内容自动探测 markdown anydoc.to_markdown_bytes(data) # 3) 显式指定格式——无签名的格式CSV必须显式命名 markdown anydoc.to_markdown_bytes(data, csv) # 4) 停在文档模型上同时保留嵌入资源图片、OLE 对象等 document anydoc.to_document(data)三种入口的类型签名以类型桩为准python/anydoc/_anydoc.pyi函数签名说明to_markdown(path: str \| os.PathLike[str]) - str读取文件并转换格式先按内容探测失败时回退到扩展名to_markdown_bytes(data: bytes \| bytearray, format: Format \| None None) - str内存转换不传format时按内容探测to_document(data: bytes \| bytearray, format: Format \| None None) - Document解析为文档模型携带blocks、notes、assets三个行为细节值得注意to_document不支持 PDF。PDF 走独立的 pdf-inspector 路径直接产出 Markdown没有文档模型形态python/src/lib.rs 的文档注释明确写了这一点需要 PDF 时请用to_markdown_bytes。to_markdown只读文件失败时抛OSError家族异常如FileNotFoundError而不是ConvertError见 python/src/lib.rs 中Io变体被原样透传回 Python 的处理。传入不存在的格式名会抛ValueError。parse_formatpython/src/lib.rs会报unknown format ...; expected one of ...测试 python/tests/test_anydoc.py 用anydoc.to_markdown_bytes(b, wat)验证了这一点。并发与 GIL 行为所有转换都在py.detach(|| ...)中执行如 python/src/lib.rs即转换期间释放 GIL。这意味着在to_markdown/to_markdown_bytes/to_document执行时Python 解释器的其他线程可以继续运行——批量转换大量文档时配合concurrent.futures.ThreadPoolExecutor可以获得真实的并行度而不是被 GIL 串行化。这是纯 Python 解析库做不到的收益也是文档中conversion releases the GIL, so other threads keep running这句话的底层来源。错误处理细粒度的异常体系转换只在无法产出有意义的 Markdown 时才抛异常可恢复的瑕疵如某个样式缺失、某段内容损坏会被跳过并继续不会打断整个转换。异常类型直接对应失败原因try: return anydoc.to_markdown(path) except (anydoc.EncryptedError, anydoc.UnsupportedError) as error: # 这类文件完全无法产出文档记录后处理下一个文件 unconverted.append((path, type(error).__name__)) return None异常对照表来自 python/README.md语义可在 src/error.rs 中印证异常触发时机UnsupportedError格式未知或根本无法转换例如纯图片 PDF需要 OCRMalformedError结构上不可用提取不到有意义的内容EncryptedError文件被加密或受密码保护ResourceLimitError越过固定安全上限解压、嵌套深度、节点数等MissingPartError产出有意义输出所需的部件缺失OSError文件读取失败仅to_markdown关键设计是异常继承关系前五种转换失败都继承自anydoc.ConvertError所以只捕获ConvertError就能一次性兜住所有转换失败而OSError不在此列需要单独处理。在 python/src/lib.rs 中这五个异常通过 pyo3 的create_exception!声明ConvertError是基类其余五个是它的直接子类。几个携带诊断信息的属性MalformedError.part和MissingPartError.part指出出问题或缺失的包部件或流名称。例如测试里构造了一个只含空[Content_Types].xml的 docx 包抛出的MissingPartError.part word/document.xmlpython/tests/test_anydoc.py。ResourceLimitError.limit指出被越过的上限名。测试用 zip 炸弹夹具验证limit max_entry_bytespython/tests/test_anydoc.py。str(error)完整的错误消息方便直接记日志。MalformedError.part在无法定位单一部件时为None。与 Node/wasm 绑定不同它们通过error.code发布变体名Python 直接抛不同的异常类语义一一对应unsupported、malformed、encrypted、resourceLimit、missingPart见 src/error.rs 的code()及对应测试。固定安全上限ResourceLimit 背后的硬约束ResourceLimitError不是可配置项而是 anydoc 针对恶意/病态输入设置的硬上限见 src/package/limits.rs 的开头注释刻意不可配置真实文档离这些值差几个数量级。主要上限包括上限默认值约束对象MAX_ENTRY_BYTES128 MiB单个压缩条目解压后的大小MAX_TOTAL_BYTES512 MiB单个压缩包累计解压字节MAX_ENTRY_COUNT100 000单个压缩包的条目数MAX_XML_DEPTH256XML 元素嵌套深度MAX_XML_NODES2 000 000单个部件中的 XML 节点数元素 文本MAX_EXPANSION4 000 000单表重复展开产生的承载内容单元格数MAX_EXPANSION_TEXT_BYTES64 MiB重复展开导致的总文本复制字节数MAX_ASSET_TOTAL_BYTES128 MiBDocument中保留的嵌入资源总字节数MAX_RECORD_DEPTH64旧版 PPT 二进制记录容器的嵌套深度MAX_RECORDS16 000 000单个旧版记录流访问的总记录数这些上限主要针对解压炸弹、病态嵌套、指数式展开等攻击形态测试夹具目录 tests/fixtures/abuse/ 里就有zipbomb--errors.docx、imagebomb--errors.docx、deepnest--errors.ppt等对应的对抗样本。格式探测读内容不读扩展名anydoc 的格式探测基于内容特征而非文件名按照各格式规范指定的标记来识别。探测逻辑集中在 src/formats/detect.rsPDF%PDF-头ISO 32000实现允许前置垃圾字节探测时在 1024 字节窗口内查找RTF每个 RTF 文件必须开头的{\rtf组OLE 复合文件[MS-CFB] 签名后按二进制 Office 格式强制要求的流名识别——WordDocumentdoc、PowerPoint Documentppt、Workbook/Bookxls大小写不敏感ZIP 包按包的自我标识识别——ODF/EPUB 看mimetype部件OPCdocx/pptx/xlsx看包级 officeDocument 关系指向主部件的内容类型内容类型陈旧或泛化时回退到主部件强制根元素w:document、p:presentation、workbook再不行回退到约定俗成的部件路径。CSV 没有签名所以内容探测对它返回None必须靠扩展名或显式传format来命名。Python 侧提供了三个探测函数anydoc.format_from_bytes(data) # docx或无法匹配时返回 None anydoc.format_from_extension(.pptm) # pptx——容器变体映射到共享解析器 anydoc.format_from_path(report.odt) # odt三个函数的行为python/src/lib.rsformat_from_bytes(data)纯内容探测返回 12 个规范格式名之一或Noneformat_from_extension(ext)扩展名命名格式带不带前导点都行.pptm和pptm等价.docm、.pptm、.xlsm等容器变体会映射到docx/pptx/xlsxformat_from_path(path)取路径扩展名命名格式。测试验证了这些行为python/tests/test_anydoc.pyformat_from_bytes(rich_docx_bytes) docxformat_from_bytes(csv_bytes) is Noneformat_from_extension(.pptm) pptxformat_from_extension(xls) xlsxformat_from_path(report.unknown) is None。值得强调的一个工程细节探测优先级是内容优先于扩展名。to_markdownsrc/lib.rs先做Format::from_bytes失败才回退Format::from_path所以即使扩展名被错误命名只要内容特征清晰比如把 docx 改名为.txt依然能正确转换反之内容无法识别而扩展名可识别时也能兜底。在 src/formats/detect.rs 的测试中还有一个专门用例zip 包内嵌%PDF-的 PDF 文件时容器签名PK\x03\x04 关系优先于内部 PDF 头正确判为 docx。文档模型与嵌入资源to_document返回的Document是一个冻结的解析结果不是可变的构建器所有类都用#[pyclass(frozen, get_all)]声明属性只读python/src/document.rs。枚举变体统一以 snake_case 字符串暴露在kind属性上负载放在可选的具名属性里——这是与 Node 绑定一致的形状设计。Document包含三个字段blocks: list[Block]顶层内容块notes: list[Note]脚注和尾注正文正文中通过note_ref内联引用其idassets: list[Asset]嵌入的二进制资源。Block的kind有七种取值负载属性随之变化kind关键属性headinglevel1–6、anchor文档内有内部链接指向标题时的稳定锚点 id、contentparagraphcontentlistlist含marker、start、itemstabletable含grid、header_rows、kindblock_quoteblocks嵌套块code_blocklang、textrule无Inline的kind有六种text、link、image、anchor内部链接目标的零宽标记、note_ref、line_break。文本内联携带完全解析后的字符样式Stylebold、italic、strike、code四个布尔值。链接目标LinkTarget区分external带 scheme 的绝对 URL、relative无 scheme 的相对引用按原样保留、anchor内部目标。图片源ImageSource区分external带 URL、asset嵌入资源通过asset_id索引到Document.assets、unavailable部件缺失或不可读只剩 alt 文本。表格采用规范化网格表示每个逻辑网格位置恰好出现一次合并单元格的内容和跨距放在源格CellSlot.kind origin上被覆盖的位置是covered槽通过origin_row/origin_col指回源格python/src/document.rs。Table.kind区分data真实数据表和layout文本框、定位表等布局脚手架。嵌入资源Markdown 承载不了字节模型可以Markdown 无法内嵌二进制所以嵌入图片在 Markdown 里渲染为其 alt 文本而原始字节保留在document.assets上每个Asset带media_typeMIME 类型如image/png和origin_part来源部件或流用于溯源带外部 URL 的图片则渲染为普通 Markdown 图片。Asset的字段为id、media_type、origin_part、databytes测试里用to_document验证了 PNG 资源能以bytes形式取回且id与列表索引一致python/tests/test_anydoc.py。这个设计意味着两类常见场景都很顺手只想快速拿文本用to_markdown/to_markdown_bytes一次调用得到成品 Markdown需要处理图片用to_document拿到模型遍历blocks找kind image的内联看source.kind对asset类型的用asset_id去document.assets取原始字节自行落盘或转存如上传对象存储后在 Markdown 里替换为可访问 URL。另外to_markdown输出的是GitHub-Flavored Markdown标题锚点、表格管道转义、任务列表、脚注等输出行为对所有输入格式统一详见仓库根 README.md 的 Features 一节这也是任何格式进来、输出一致的承诺来源——所有格式先解析进同一个共享文档模型再经同一个 Markdown 序列化器渲染架构图见 README.md 的 How it works 一节。常见实战模式把官方示例和测试组合起来几个高频模式可以直接照抄批量转换 汇总失败import anydoc from pathlib import Path unconverted [] for path in Path(inbox).glob(*): try: markdown anydoc.to_markdown(path) except anydoc.ConvertError as error: # 记录失败文件与具体原因继续处理下一个 unconverted.append((path.name, type(error).__name__, str(error))) continue Path(out, path.stem .md).write_text(markdown, encodingutf-8)从网络/存储读字节显式命名 CSVdata response.read() # 或从 S3/OSS 等读到的 bytes markdown anydoc.to_markdown_bytes(data, csv) # CSV 无签名必须显式命名先探测再决定处理路径fmt anydoc.format_from_bytes(data) if fmt is None: # 无签名试试扩展名 fmt anydoc.format_from_extension(report.csv) if fmt pdf: # PDF 无文档模型直接转 Markdown markdown anydoc.to_markdown_bytes(data, pdf) else: document anydoc.to_document(data, fmt) for asset in document.assets: ... # 处理嵌入图片等资源借助 GIL 释放做并行转换from concurrent.futures import ThreadPoolExecutor with ThreadPoolExecutor(max_workers8) as pool: results list(pool.map(anydoc.to_markdown, files))进一步探索完整的行为说明与基准数据质量打分、各格式逐项对比、中位转换耗时见仓库根 README.md 的 Benchmark 一节Python 绑定的完整 API 形状以类型桩 python/anydoc/_anydoc.pyi 为准测试 python/tests/test_anydoc.py 保证桩与实现同步格式探测的完整实现与边界用例在 src/formats/detect.rs安全上限在 src/package/limits.rs错误语义在 src/error.rs项目同时提供 Node.js 绑定node/README.md、WASM 绑定wasm/README.md以及 Rust 原生 APIsrc/lib.rs各端 API 形状保持一致。赞分享AI 技能【免费下载链接】anydocConvert Word, PowerPoint, Excel, OpenDocument, RTF, EPUB, CSV, and PDF to clean Markdown. Built in Rust, with Node.js and Python bindings.项目地址https://gitcode.com/gh_mirrors/any/anydoc点击查看免费下载相关推荐Caddy-docker与PHP-FPM集成现代化PHP应用部署的终极解决方案Caddy docker与PHP FPM集成现代化PHP应用部署的终极解决方案 在当今快速迭代的Web开发领域选择高效可靠的服务器配置对项目成功至关重要。CAI 技能NanoClaw 中安全移除 AnyDoc 文档转换功能完整回滚与重建指南NanoClaw 中安全移除 AnyDoc 文档转换功能完整回滚与重建指南 NanoClaw 通过 add anydoc 技能为运行在容器内的 Agent 安人工智能AI 应用AI AgentAgent 沙箱交互助手WeKnora 内嵌 anydoc-goRust 办公文档解析器的 cgo 绑定、安全升级与构建实践WeKnora 内嵌 anydoc goRust 办公文档解析器的 cgo 绑定、安全升级与构建实践 导读 本指南深入剖析 WeKnora 中 third_p人工智能大模型RAGAI Agent后端前端MCP 服务知识库dsh-plugin工具调用上一篇解决KernelSU模块注入系统应用失效的完整指南从原理到实战修复下一篇5分钟掌握hugo-PaperMod阅读时间计算从实现到定制的用户体验优化指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考