资讯详情

资讯详情

Docling本地文档转换实战:PDF扫描件与表格智能转Markdown

前阵子朋友让我帮忙处理一批扫描版技术合同要把它们转成能进知识库的结构化文本。这类材料一份都不能传外网在线转换站我试了一圈要么免费额度只够转前几页要么表格彻底乱掉输出的 Markdown 根本没法直接入库。后来我把转换工具换成本地开源的 Docling才真正把 PDF、扫描件图片和复杂表格批量转成了干净的 Markdown。这篇把踩过的坑和实测结果一起记录下来给正在找本地文档转换方案的朋友做个参考。1. 为什么我放弃了在线转换工具1.1 在线转 Markdown 的几个让人崩溃的坑先说说我为什么绕了一大圈才转到本地工具。以前图省事习惯把 PDF 拖进某个在线转换平台几分钟后下载 Markdown。这种模式在日常遇到三五页简单文档时确实能用但一旦文件稍微正经一点问题就全冒出来了。第一个是大小和页数的限制。我遇到过一份 12MB 的扫描版说明手册某在线平台要求充值会员才能完整转换免费版只允许处理前 5 页。你想想一份手册最核心的表格往往就在中间几页想要全文就得反复试不同平台每家的免费额度还都不一样折腾半天纯属浪费时间。第二个是表格处理能力太弱。财务报表、采购清单这类带合并单元格和复杂表头的 PDF在线工具转出来的 Markdown 经常是列对不齐、跨页断行、表头信息丢失。有一次我转一份对账单原表本来有 6 列转换后只剩 4 列还有两列数据全挤在一个单元格里。手动修这种表比自己重新做一份还要久。第三个是隐私风险。我的工作里经常涉及内部报价、合同扫描件、客户名单这些材料传到第三方服务器上等于把数据控制权交了出去。你永远不知道平台会不会留存、会不会被拿去训练模型这对做企业资料整理的人来说是硬伤哪怕只是个人使用上传身份证复印件之类的材料也要多留个心眼。第四个是隐性收费和广告套路。免费版导出带水印下载前要等倒计时页面里穿插各种诱导开通会员的按钮。我也不是不能理解平台要盈利但很多在线工具的核心转换质量根本不配那个价格体验非常劝退。1.2 最终选择 Docling 的原因转过一圈之后我给自己定了几条硬性标准必须本地运行、必须开源、输出格式要标准、表格识别不能太拉胯。Docling 恰好满足这些要求。Docling 是一款开源文档解析工具核心任务就是把 PDF、图片等输入转换成结构化的 Markdown 和 JSON。它和普通 PDF 转文本工具最大的区别在于它不是简单地把每一页的字符抽出来拼接而是先做版面分析识别出标题、正文、列表、表格、页眉页脚这些区域再按照阅读顺序重组内容。换句话说它更像一个“懂排版”的阅读助手而不只是一个文本提取器。我选择它还有一个很实际的理由完全本地运行。模型和代码都跑在自己机器上断网也能用敏感材料不用上传任何人。开源意味着我可以审计整个处理流程出了问题能查、能修、能改这一点对技术型用户来说非常重要。1.3 这次实测我准备了哪些材料为了把 Docling 的真实水平摸清楚我准备了一组有代表性的测试材料一篇双栏排版的英文论文用于测试阅读顺序重组一份 20 页中英文混排的扫描版合同用于测试 OCR 能力一份带合并单元格和跨页表格的财报 PDF用于测试表格结构保真度还有几张手机拍的截图和扫描图片看看它能不能直接吃图片输出 Markdown。每一类材料我都分别记录转换速度、格式完整度、表格结构保真度和出错的典型位置。下面就从环境搭建开始一步步说。2. Docling 环境准备和第一个转换结果2.1 安装 Docling建议用干净环境Docling 的安装本身不复杂pip 一行就能搞定但我强烈建议先建一个干净的虚拟环境不要直接往系统 Python 里装。原因是 Docling 会带上一堆机器学习和文档解析相关的依赖和某些全局包版本冲突起来非常头疼。我在测试机上是用 venv 创建独立环境做的过程如下python -m venv docling-env source docling-env/bin/activate # Windows 下用 docling-env\Scripts\activate pip install --upgrade pip pip install docling安装过程会根据你的 Python 版本拉取对应依赖其中包含 PyTorch 相关组件包比较大耐心等一会儿就好。Docling 要求 Python 3.10 或更高版本装之前先确认一下环境版本免得装到一半报错。如果你打算用 GPU 加速处理大批量文档安装时可以选择带 CUDA 支持的版本否则默认走 CPU 推理也完全够用只是大批量处理时速度会慢一些。我自己的日常测试大多在 CPU 上跑的后面细说。2.2 第一次跑通命令行PDF 转 Markdown安装完成后Docling 自带命令行工具最简单的用法就是把 PDF 丢给它docling contract.pdf执行后会在当前目录生成一个out文件夹里面放着转换好的 Markdown 文件。第一次运行会下载模型文件需要等待一段时间之后再用就有缓存了。命令行默认情况下会输出一份 Markdown同时也会生成对应的 JSON 文件。这个过程非常省事一条命令就能完成“电子版 PDF 转 Markdown”。我第一次拿一份带图表的单栏文档测试输出的 Markdown 里标题层级、段落顺序、列表结构基本都正确表格也能以标准 Markdown 表格语法呈现当时就觉得这工具比在线平台靠谱。2.3 首次运行时的模型下载与缓存策略刚提到首次运行会下载模型这里多说一句。Docling 的版面分析、表格结构识别、OCR 等能力依赖于多套预训练模型这些模型托管在公共模型仓库中第一次调用时会自动下载到本地缓存目录。你的机器磁盘如果比较紧张建议提前把模型缓存指到剩余空间大的数据盘上。我自己的做法是先跑一个最小文件让模型下载完成然后找到系统用户目录下的模型缓存文件夹把它直接软链到数据盘。这一步能避免 C 盘不知不觉被几个 GB 的模型文件塞满。如果之后发现模型损坏或者版本异常删掉缓存重新让 Docling 拉取一遍就行。只要模型已经缓存之后即使断开网络也能正常完成本地转换这点在敏感环境下尤其实用。3. 核心功能实测PDF、图片、表格3.1 电子版 PDF标题结构、段落和阅读顺序先看最简单的场景输入一份本身带文字层的 PDF。这类 PDF 不需要 OCRDocling 可以直接读取内嵌文本但关键考验在于版面分析。我拿一篇双栏学术论文做测试转出来的 Markdown 开头是这样的# Title: 论文主标题 **Abstract.** 这一段是摘要内容…… ## 1. Introduction 第一段正文…… | Table 1 | 特征A | 特征B | | --- | --- | --- | | 方法X | 0.92 | 0.87 |最让我满意的是双栏阅读顺序没有乱。很多工具直接把双栏 PDF 的每一行文本从左到右硬拼结果两栏内容交叉混在一起根本读不通。Docling 对版面区域做了排序输出的内容基本是“先读完左边一栏再读右边一栏”的自然顺序标题层级也忠实保留了。代码块和列表的处理也符合预期。如果有缩进的列表或者有序列表它会对应转换成 Markdown 列表语法而不是把缩进空格原样保留的纯文本。这一点在整理技术文档时非常实用。3.2 扫描件和图片中文 OCR 到底行不行扫描件是很多 PDF 转换工具的死穴因为文字以图片形式存在没有文字层可提取。Docling 的做法是自动启用 OCR把图像中的文字识别出来再重组结构。我拿扫描版合同测试20 页中英文混排合同里有印章、手写批注、模糊的复印痕迹识别结果比免费在线工具高出一大截。常见的中文宋体、黑体印刷文字识别准确率相当高段落顺序也基本正确。但有几个位置因为原稿印章盖在文字上导致笔画粘连识别出来之后个别字会出错。这个不怪 OCR换哪个工具都难处理原稿质量是上限。图片输入方面Docling 同样可以直接处理 jpg、png 等常见格式。我试了一张手机拍的纸质表格照片只要拍得端正、光线均匀转出来的表格结构完整度也不错。换句话说你手里的资料如果是一堆图片完全不需要先拼成 PDF直接交给 Docling 就能得到 Markdown。OCR 的语言配置在 Python API 里更清晰我放到第 4 部分详细讲。注意OCR 语言包和版面模型一样首次使用需要联网下载。如果转换出来全是乱码优先检查语言参数是否正确配置常见的中文场景建议同时启用“zh”和“en”两种语言。3.3 复杂表格合并单元格、跨页和网格线表格是这次测试里我最关注的部分。现代文档里表格早就不是规规矩矩几行几列了表头有多层结构单元格会跨列合并整张表还会跨页拆分。这是在线工具最容易翻车的地方。Docling 的表格处理做得比较深。它用专门的表格结构模型去识别每个单元格的位置、行列归属以及合并关系然后转成 Markdown 表格。我用一份财报 PDF 测试原表带多级表头和跨页的大表转出来的 Markdown 表格虽然不能做到和原表像素级一致但行、列、合并单元格的主要语义保住了配合 JSON 输出可以拿到更精确的结构信息。有个经验分享如果某个表格在原 PDF 里是跨页的直接转换时 Docling 有时会把两页的表格拆成两个独立的 Markdown 表格需要后续手动合并。我常用的补救手段是把这个表格单独从 PDF 里裁剪成高清图片再让 Docling 走“图片转 Markdown”的路径重新识别效果往往比直接解析带文字层的跨页 PDF 更完整。3.4 公式、代码块和双栏版面的最终表现技术类 PDF 还有一个常见需求是把公式转成可复用的格式。Docling 内置了公式识别能力把印刷公式转换成 LaTeX 语法再嵌入 Markdown 中。这意味着数学公式不再是一张无法编辑的图片而是可以复用的文本。实测下来清晰印刷的公式基本能正确转换手写公式就别指望了那个需要专门的公式手写数据集训练不在这个工具的定位内。代码块方面Docling 会把带背景色或等宽字体的区域识别为代码块并尝试保留语言特征。我发现它对带缩进和注释的 Python 片段识别得不错但对某些高亮样式特别的代码块可能只会转成普通段落需要在输出后手动修正。双栏版面在开启 OCR 重排后会更稳定。原因也很简单当 PDF 自带文字层时Docling 依赖源文件的内嵌顺序来判断阅读路径如果源文件本身的内嵌顺序和视觉顺序不一致就可能出现段落交错。强制 OCR 整页重排之后所有文字都以图像方式重新识别等于让模型完全按视觉布局来重组阅读顺序反而更可靠。4. 用 Python API 做定制化转换4.1 最简 API 调用命令行虽然方便但真实项目里通常需要在程序里批量处理文档这时必须用 Python API。Docling 的 API 设计得非常简洁几行就能跑通from docling.document_converter import DocumentConverter converter DocumentConverter() result converter.convert(sample.pdf) markdown_text result.document.export_to_markdown() print(markdown_text[:500])convert()方法接收文件路径、URL 或者二进制流返回一个结果对象。result.document是一棵结构化的文档树里面按区块保存了标题、段落、表格、列表等元素。export_to_markdown()则把这棵树序列化成 Markdown 文本。这个设计的好处是你可以只取 Markdown也可以进一步操作每个区块的元数据。4.2 控制 OCR 开关和语言参数对于扫描件或需要强制视觉重排的场景我们需要显式打开 OCR 并指定语言。以我实际使用的中文扫描合同为例配置方式如下from docling.document_converter import DocumentConverter from docling.datamodel.pipeline_options import PdfPipelineOptions pipeline_options PdfPipelineOptions() pipeline_options.do_ocr True pipeline_options.ocr_options.lang [zh, en] converter DocumentConverter(pipeline_optionspipeline_options) result converter.convert(scan_contract.pdf) with open(scan_contract.md, w, encodingutf-8) as f: f.write(result.document.export_to_markdown())需要注意不同版本的 Docling 参数名偶尔会微调但核心思路是一致的通过PdfPipelineOptions控制处理流程OCR 语言用列表传多个值中英混排文档建议把“zh”和“en”一起放进去。如果你有大量纯中文文档也可以只配“zh”一个语言速度会快一点。4.3 批量转换脚本把整个目录的 PDF 全转掉现实里很少只转一两份文件更多情况是一个目录里躺着几十份 PDF。写一个批量脚本不难但我踩过一个坑没有检查“目标文件是否已存在”导致脚本中途断掉后重跑前面转过的文件又要重新转一遍。后来我加了一层判断已经存在同名 MD 文件就直接跳过实现类似断点续传的效果from pathlib import Path from docling.document_converter import DocumentConverter converter DocumentConverter() def convert_pdfs(src_dir: Path, out_dir: Path) - None: out_dir.mkdir(parentsTrue, exist_okTrue) for pdf in src_dir.glob(*.pdf): target_md out_dir / f{pdf.stem}.md if target_md.exists(): print(fskip: {pdf.name}) continue result converter.convert(pdf) target_md.write_text(result.document.export_to_markdown(), encodingutf-8) print(fdone: {pdf.name}) if __name__ __main__: convert_pdfs(Path(./input), Path(./output))这个脚本帮我处理了几百份归档文件实际跑下来稳定性不错。处理中途如果某一页识别特别慢我也没必要干等直接中止重跑反正已完成的文件会被跳过。4.4 除了 Markdown还能输出 JSON很多人在意 Markdown 是因为它可读性好但机器处理时 JSON 往往更有价值。Docling 的文档树可以直接导出成字典或 JSON 文件doc_dict result.document.export_to_dict() with open(output.json, w, encodingutf-8) as f: json.dump(doc_dict, f, ensure_asciiFalse, indent2)JSON 里保存了每个区块的类型、层级、表格行列结构和坐标等信息。它最大的价值在于当我们想提取“第三个表格的单元格内容”或者“第一页的所有标题”时不需要去解析 Markdown 文本直接从结构化数据里取就行。对程序化处理来说JSON 输出比纯 Markdown 可靠得多。4.5 接入知识库和 RAG 场景的真实体验如果你在搭知识库或者做 RAG 问答系统Docling 的这些输出格式就非常关键。过去我们做文档分块时经常按页或按固定字数盲目切文本结果表格被从中间切断、标题和正文分离检索效果很差。我的做法是先用 Docling 把文档转成 Markdown 或 JSON再根据标题层级对文档做语义分块。表格部分直接保留 JSON 结构让每个单元格的坐标和行列信息完整进入向量库。这样在问答检索时模型能拿到完整表格语义而不是一段被切碎的 TSV 文本。实测下来针对结构化数据较多的文档这种处理方式对回答准确率的提升非常明显。5. 避坑指南与常见问题排查5.1 表格还是会翻车的几类情况尽管 Docling 的表格识别很强但并不是所有表格都能完美复现。我梳理了几类比较容易翻车的场景方便你提前判断场景表现建议解法多级表头和大量合并单元格行列关系偶尔丢失出现多出一条空行用 JSON 输出检查实际行列结构跨页大表格被拆成两个表格表头重复裁剪成高清图片单独转换扫描件表格线不连续单元格边界识别错误提高原图分辨率尽量让网格线清晰无框线表格模型可能漏判边界先手工加线或用工具补框后转换表格本身就是文档结构化里最难的一环任何工具都不能做到 100%。给原稿一个更好的图像质量比指望模型变魔法有效得多。我的经验是遇到关键表格不要只依赖一次转换结果把同一份表格用“PDF 直接转”和“图片 OCR 转”两条路都跑一遍再对比 JSON 结构取更完整的一份。5.2 中文 OCR 效果不理想时的排查顺序如果你发现转换出来的中文文本错别字比较多先别急着下“工具不行”的结论按这个顺序排查第一确认 OCR 语言配置里加了“zh”只配默认英文当然会乱第二看原始 PDF 分辨率低于 200 DPI 的扫描件识别效果会明显下降第三看页面方向是否正确有些扫描件是歪的或者 180 度旋转的需要先校正第四遇到复杂背景或印章遮挡基本无解需要原稿更干净。还有一个细节OCR 引擎对常见印刷字体的识别率很高但遇到艺术字、手写体、特殊符号时会出错。这类内容不是 Docling 的问题任何通用 OCR 模型都难以搞定。如果资料里手写批注是你的核心内容建议使用专业手写识别方案而不是纠结于文档转换工具。5.3 模型下载慢、磁盘占用大怎么办Docling 首次使用要拉取多套模型加起来可能有好几个 GB。如果网络状况一般这个过程确实会让人焦虑。我的建议是找一台网络稳定的机器先跑一个小文档把模型完整下载好之后把模型缓存目录拷贝到其他机器上使用这样就不用每台机器都重新下一遍。磁盘占用的问题前面提过把缓存目录软链到数据盘是我目前最省心的做法。另外注意如果更新 Docling 版本之后首次转换明显变慢那很可能是新版模型需要重新缓存一部分文件属于正常现象。5.4 双栏版面还是乱掉时的补救手段大多数双栏 PDF 在 Docling 下都能正确重排但极个别排版特殊的文档仍会出问题比如三栏版面、多级脚注密集的页面。遇到这种文件我尝试过几种补救方式按效果排序先开启强制整页 OCR 重排这一步能解决大部分内嵌文字顺序问题然后把 PDF 按页放大转成高清图再走图片识别流程如果还是乱就导出 JSON根据区块坐标自己重排内容。最后这种方案比较费时间但它在理论上是最可控的。5.5 我实测后一直沿用的参数组合下面这组参数是我处理中英文混排、带表格和双栏版面的文档时经常使用的pipeline_options.do_ocr True pipeline_options.ocr_options.lang [en, zh] pipeline_options.table_structure_options.do_cell_matching Truedo_ocr开启后扫描件和带文字层 PDF 都会走统一的视觉识别流程版面重排更稳定。语言列表覆盖中英文混排场景。最后一个参数用于让表格单元格与识别出的文本做匹配对齐能减少表格张冠李戴的问题。不同版本的参数名可能有差异以你安装的版本为准但这个配置思路本身是通用的。如果你的机器性能偏弱可以只对关键文档开整页 OCR普通文档关闭 OCR 走纯文本层解析速度会快很多。6. 我的最终评价和适用场景用了一段 Docling 之后我对它的定位已经很明确了它适合批量处理以文字和表格为中心的文档把资料从“不可检索的 PDF”变成“可编辑、可检索、可入库的 Markdown 和 JSON”。整理论文、归档合同、清洗报表、搭建个人知识库这些都是它的主场。它不太适合对排版保真度要求极高的场景比如你要输出一份和原 PDF 完全一样的 Word 文档或者原稿是复杂手写笔记这类任务 Docling 不是最优解。我个人体会最深的一点是不要盲目拿一个工具从头用到尾而是先找一份包含标题、表格、扫描页、跨页内容的复杂文档测试不同参数组合确定一套最适合自己材料的配置模板。这样后续批量处理时非常省心。最后再分享一个小技巧。遇到那些内嵌字体或编码有问题的 PDF直接在转换前用虚拟打印机“打印成 PDF”重新生成一份哪怕只是把文件过了一遍打印机驱动也能消掉很多奇怪的字符错乱问题。我后来处理一批旧版软件导出的 PDF 时就是用这个方法先清洗了一层再喂给 Docling成功率立刻上来了。这个流程特别适合处理来历不明、制作工具老旧的 PDF 文件。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →