)
前段时间整理历史资料手头攒了不少 PDF扫描版的合同、带复杂表格的财报、双栏排版的期刊论文。我最初的诉求很朴素——把它们变成干净的 Markdown扔进知识库和 RAG 流程里。试了一圈工具要么表格提取出来全是乱的要么扫描件直接歇菜要么栏序、阅读顺序一塌糊涂。直到朋友推荐了 docling一个把 PDF 解析当成完整 pipeline 来做的开源工具我才发现以前折腾的方向本身就错了。这篇文章就把 docling 的原理、安装、命令行和 Python API、实操效果、以及我在真实文档上踩过的坑完整捋一遍给同样被 PDF 折磨过的同学一个可以直接参考的路线。1. 从“PDF 复制出来是乱的”说起docling 在解决什么问题1.1 PDF 对解析器来说根本不是“文档”很多人第一次遇到 PDF 解析问题都是从复制粘贴开始的。选中一段文字粘到记事本里发现换行全没了表格变成了空格串双栏的论文左右两块内容混在一起。原因也很简单PDF 文件本质上是一份“页面排版说明书”记录的是每个字符放在页面哪个坐标位置而不是“标题、段落、表格”这样的逻辑结构。所以任何 PDF 解析工具无论底层是 PDF 规范直接读取还是走 OCR 识别第一步都要先做一件事版面分析也就是从坐标和像素里猜出哪些文本属于同一个段落、哪个区域是表格、哪块是页眉页脚。传统工具像 pdfplumber、PyMuPDF 处理简单排版的单栏文档还好一旦遇到多栏、复杂表格、图片型扫描件就基本只能靠“人工接管”了。1.2 docling 的全链路解析思路docling 和传统 PDF 库最大的不同在于它把这件事拆成了完整的 pipeline而不是只给你一个“提取文本”的函数。它背后是 IBM 开源的一系列文档理解模型整个处理链路大概是这样读取把 PDF 或 DOCX、PPTX 等文件读进来统一转成内部文档表示版面分析用模型识别页面上的标题、正文、图片、表格、页眉页脚等区域阅读顺序排序判断内容在视觉上从上到下、从左到右的真实阅读路径而不是简单按 PDF 内部对象顺序输出表格结构识别针对表格区域重建行列结构和合并单元格OCR 兜底如果 PDF 本身没有文本层比如扫描版会自动调用 OCR 引擎把图像转成文字统一导出最后输出 Markdown、HTML、JSON 或纯文本。这个设计思路很像一位排版编辑在处理原稿先看整页布局再按阅读顺序整理内容最后单独对付表格和图片。所以它输出的 Markdown 是“能直接读、能在网页上正常渲染”的那种而不是一堆文字残骸。1.3 它到底适合哪些人如果你只是偶尔从 PDF 里复制几行字那 docling 属于杀鸡用牛刀但如果你在做这类事情它就很值得试要把大量 PDF 转成 Markdown 放进知识库或 RAG 检索需要稳定恢复表格结构尤其是带合并单元格的报表需要处理扫描版 PDF 和图片型文档想在一个标准文档模型上做二次开发比如信息抽取、文档比对。一句话概括docling 不是“PDF 文本提取器”而是“文档结构还原器”。2. 安装 doclingPyTorch、模型缓存与第一时间跑通2.1 环境准备Python 版本、虚拟环境、pip 依赖docling 的安装并不复杂但有一点必须提前有心理准备它的依赖非常重。因为要跑深度学习模型安装时会自动拉入 PyTorch、transformers、huggingface-hub 这一整套生态装完往往几百 MB 起步。所以第一步强烈建议用一个干净的 Python 虚拟环境不要直接往系统 Python 里怼。我用的是 Python 3.10docling 目前对 Python 版本也比较挑太老的 3.7、3.8 大概率装不上建议直接用 3.10 或 3.11。python -m venv docling_env source docling_env/bin/activate pip install docling如果你在 macOS 上可能还需要先装一下 libmagic 之类的系统依赖具体报错后按提示补即可。安装完成后可以用pip show docling确认版本顺便看一眼依赖列表心里有个数。2.2 首次运行模型文件从哪来、缓存到哪里安装只是第一步。第一次真正转换文档时docling 会下载版面分析、表格结构识别和 OCR 相关的模型文件。这些模型默认从 Hugging Face Hub 拉取缓存目录通常在~/.cache/huggingface/hub下。我第一次跑的时候不知道这个流程命令执行后半天没动静以为卡死了。其实是在后台下载模型日志也提示得不够明显。如果你网络环境访问 Hugging Face 不顺畅有两个办法一是配置镜像环境变量然后再次运行export HF_ENDPOINThttps://hf-mirror.com二是提前在有网络的环境里把模型下载好然后把整个~/.cache/huggingface目录复制到目标机器。离线时设置HF_HUB_OFFLINE1docling 就会直接用本地缓存。提示模型下载是“首次运行才触发”所以准备一个干净环境后先拿一个小文件试跑一次把模型缓存热好后面正式处理大文档会顺很多。2.3 装完先跑一个最小验证装好之后直接用一个单页 PDF 验证整条链路是否通畅。比如你随便导出一页 PDF然后执行docling sample.pdf --to md如果看到类似“success”的日志并且当前目录出现sample.md说明模型加载、版面分析、导出都正常后面就可以正式用了。3. 命令行实操一条命令把 PDF 变成 Markdown3.1 基础命令与输出结果docling 的命令行设计得很直觉核心就是docling 文件 --to 格式。最常用的组合是把 PDF 转成 Markdown顺便指定输出目录docling report.pdf --to md --output-dir ./output执行结束后./output下会生成一个report.md。这个 Markdown 可不是简单的文字拼接它已经包含了一级、二级标题层级列表、表格、代码块都会按结构生成。拿一篇双栏论文试过docling 能把左右两栏的内容按正确的阅读顺序串成一篇连续文本这一点是很多传统 PDF 库做不到的。3.2 输出格式和保存位置除了 Markdowndocling 还支持 JSON、HTML、纯文本等格式。其中 JSON 格式我最常用因为它保留了完整的版面信息每个标题的层级、每张表格的行列坐标、图片的引用位置甚至阅读顺序全都结构化地放在里面。如果想做文档理解或信息抽取直接用 JSON 比解析 Markdown 要省力得多docling report.pdf --to json --output-dir ./output如果你想让输出的文件独立保存、不产生额外元数据可以加上--no-embed-images之类的参数来避免图片被 base64 塞进 Markdown 里。具体参数每个版本略有差异拿不准的时候先跑一下docling --help它的参数说明比我想象中完整很多。3.3 批量处理的思路docling 的命令行本身一次只处理一个文件但批量需求很常见。我的做法是在 shell 里直接循环或者写个十几行的 Python 脚本调用它的库比单纯传一堆文件名更灵活for f in ./pdfs/*.pdf; do docling $f --to md --output-dir ./output done注意处理好中文文件名shell 循环里最好给变量加上双引号免得分割出错。批量跑的时候建议先处理两三个文件确认效果再全量开跑避免一晚上出来发现输出目录里一半都是乱码。4. Python API读取、导出结构与自定义 OCR4.1 最小代码转换并导出 Markdown命令行适合一次性任务但真要集成到自己的处理流程里还是要用 Python API。docling 的 API 设计得比较直白最小可用代码只有几行from docling.document_converter import DocumentConverter converter DocumentConverter() result converter.convert(report.pdf) with open(report.md, w, encodingutf-8) as f: f.write(result.document.export_to_markdown())convert方法返回一个结果对象里面最重要的就是.document也就是 docling 标准的文档表示。拿到这个对象后你可以导出 Markdown、HTML也可以遍历里面的标题、段落、表格做进一步处理。4.2 导出 JSON结构化文档里到底有什么如果你要的不是 Markdown而是可供程序消费的结构化数据JSON 是更好的选择。导出方式很简单import json json_data result.document.export_to_json() with open(report.json, w, encodingutf-8) as f: f.write(json_data)打开这个 JSON 你会发现docling 已经把文档拆成了非常细的节点每个标题、段落、表格、图片都有自己的类型、层级和内容表格还会单独保存行列信息。这意味着你可以很轻松地实现“只抽取正文中所有表格”或者“按标题层级重组文档”这类需求而不用自己从 Markdown 里正则提。4.3 按需调整 pipeline换 OCR 引擎、开关模型docling 默认的 pipeline 是一个“全家桶”版面分析、表格识别都开着OCR 也会在检测到扫描版时自动触发。但这也会带来两个问题一是每个环节都跑模型速度慢二是有时候你根本不需要 OCR硬跑反而会把已经很清晰的文字重新识别一遍。这时候可以通过DocumentConverter的pipeline_options来控制。比如明确关闭 OCRfrom docling.document_converter import DocumentConverter from docling.datamodel.pipeline_options import PdfPipelineOptions pipeline_options PdfPipelineOptions() pipeline_options.do_ocr False converter DocumentConverter(pipeline_optionspipeline_options) result converter.convert(digital.pdf)如果反过来你处理的是扫描版 PDF可以显式指定用哪套 OCR 引擎。docling 支持 EasyOCR、Tesseract以及 macOS 上的 Vision 等。换引擎只需传入对应的 OcrOptions比如用 Tesseractfrom docling.datamodel.pipeline_options import PdfPipelineOptions, TesseractOcrOptions pipeline_options PdfPipelineOptions() pipeline_options.do_ocr True pipeline_options.ocr_options TesseractOcrOptions(lang[chi_sim, eng])这里我强烈建议能继承 PDF 原生文本层的文档尽量不要开 OCR。有一种常见情况是 PDF 里的文字其实是可复制的但用了特殊编码传统库读出来是乱码这时候很多人就无脑开 OCR。其实可以先用 do_ocrFalse 跑一遍看输出 Markdown 是否正常再决定要不要 OCR能省大量时间。5. 三类文档实测电子 PDF、扫描件、复杂表格5.1 电子版 PDF最稳的场景先说最理想的情况通过 Word 排版后导出的电子版 PDF字体正常、有文本层、没有复杂表格。这种文档交给 docling基本是“降维打击”。标题层级能正确识别加粗、斜体能保留一部分段落顺序完全正确。我用一份 40 页的项目报告测试转换完成后几乎不需要人工修正Markdown 直接可以进发布系统。这类文档用传统工具也能处理但 docling 的体验好在“省心”——你不用先清理页眉页脚也不用担心目录页码混进正文版面分析模型会自动把这些噪声识别出来。5.2 扫描版 PDFOCR 和阅读顺序扫描版 PDF 是另一个频道的挑战。没有文本层意味着所有文字都得靠 OCR 从图像里抠出来而扫描件往往又是双栏、有抬头纹、有盖章阴影OCR 结果很容易错乱。我用一份手机拍照后合成的扫描版合同测试了一下。docling 的 OCR 环节会自动触发阅读顺序处理得还行正文部分的识别准确率可以接受。但必须承认扫描件质量对结果影响非常大倾斜超过 10 度、光照不均、手写批注压在打印文字上都会显著拉低识别质量。这里有个经验扫描件处理前最好先用图像处理工具做一次纠正和增强把页面转正、拉高对比度再交给 docling。效果比让 docling 硬扛要稳得多。5.3 带复杂合并单元格的表格表格结构识别的真功夫如果说前面两类文档 docling 只是“做得更好”那复杂表格就是它真正拉开差距的地方。传统工具处理表格要么只能提取纯文本字段要么遇到合并单元格直接断行docling 用了专门的表格结构识别模型能把行列、表头、合并关系尽可能还原成 Markdown 或 HTML 表格。我用一份带跨行合并单元格的产品规格表试过输出 Markdown 后再渲染成网页整体结构基本正确。但也不是完全不出错遇到表头里套子表、跨页表格、单元格里再放图片这类极端布局行和列还是会偶尔对不上。所以涉及关键数据时不要无条件信任结果一定要抽查。6. 实战排坑模型下载、中文、内存、长文档6.1 模型下载失败或特别慢这是新用户最容易卡住的一步。docling 首次运行要拉模型如果网络不稳定可能卡在某个模型上下载一半就报错。解决办法上面提过换成镜像源或者干脆在能正常下载的机器上提前把模型缓存目录打包带过去。另外一个细节模型缓存目录最好通过环境变量固定到显眼位置方便排查export HF_HUB_CACHE/data/models/huggingface6.2 中文识别和特殊字体docling 对中文的支持整体不错普通宋体、黑体排版都能正确识别和输出。但要留意几个场景古籍、繁体竖排结果会比较差激光字体、艺术字也可能出现单字错乱文字本身有倾斜角度时OCR 容易把相近的字认混。实测下来常规横排简体中文合同、报告准确率是够用的但如果你的文档有大量生僻字或特殊排版最好人工校一遍。还有一种稳妥做法同时导出 JSON 和 Markdown用 JSON 里的坐标信息定位错字位置再针对性修正比全文通读快很多。6.3 表格合并单元格错位前面提到过复杂表格的结构识别不是百分百可靠。我遇到最多的问题是合并单元格被识别成多个独立单元格导致 Markdown 表格渲染时列数不一致。这种情况没法通过参数完全规避只能靠后处理。一个实用建议如果表格特别重要建议把 docling 的表格 JSON 单独导出来写个小脚本校验每行单元格数量发现异常时再走人工修正流程。不要等最终 Markdown 都生成完了才发现表格全乱了。6.4 内存占用和超长文档docling 跑深度学习模型内存消耗不是闹着玩的。实测处理一份上百页、图片密集的 PDF内存峰值可以到 2GB 以上。如果你的机器内存吃紧有两个办法一是把长文档拆分成多段再分别转换最后合并 Markdown。注意拆分时尽量按页边界切避免打断了正文段落。二是在 pipeline 里关掉不需要的模型比如只做文本提取不做表格识别能明显降低内存占用。7. 选型对比docling 和其他 PDF 解析工具的分工7.1 不同工具解决不同层的问题我整理了一张对比表方便你根据场景快速选型。这里说一句公道话不是哪个工具“碾压”另一个而是它们解决的问题层级不同。工具最擅长明显短板适合场景pdfplumber精确定位文本和坐标规则表格提取无 OCR复杂版面很吃力需要精确位置的局部抽取PyMuPDF速度快基础文本和图片提取排版结构重建能力弱大量简单 PDF 的快速处理camelot有线表格提取扫描版无效无版面分析规范化表格数据unstructured多格式通用解析配置重依赖多非结构化数据清洗MarkerPDF 转 Markdown深度学习中文支持一般速度偏慢英文科技文献MinerUPDF 解析中文效果佳模型较重中文文档为主的项目docling全链路文档结构还原表格强悍依赖重首个文档要下载模型知识库、RAG、复杂布局7.2 我的组合策略实际项目里我不会只用 docling 一把梭。思路是纯文本层 PDF、结构简单优先 PyMuPDF快且省内存带复杂表格、需要进知识库交给 docling扫描版先用工具做图像增强再走 docling 的 OCR pipeline结构化数据抽取用 docling 的 JSON 输出而不是 Markdown。这样组合的好处是快慢结合既避开大模型的性能开销又能让真正复杂的文档得到高质量解析。8. 放进知识库和 RAGdocling 作为文档加载器8.1 RAG 为什么需要 docling 这种结构化解析器做知识库问答的同学应该深有体会很多 RAG 项目效果不理想问题不在 embedding 模型而在于文档进知识库之前就被“切坏了”。传统 PDF 库提出来的是纯文本根本没有标题层级和表格结构切分时很容易把一个表格劈成两半检索时自然答非所问。docling 的价值在于它输出的 Markdown 保留了完整的语义结构你可以按标题层级把文档切成语义完整的块表格也能作为独立单元进入检索。这样即使不看整篇文档只检索其中一段也能保证这段内容有完整的上下文。8.2 与 LangChain / LlamaIndex 的集成思路docling 本身不依赖 LangChain 或 LlamaIndex但两个框架都有针对它的读取器可以直接对接。以 LangChain 为例社区有 Docling 相关的加载器可以把你转好的 PDF 直接加载成 Document 对象再进入后续切分和向量化流程from langchain_docling import DoclingPDFLoader loader DoclingPDFLoader(report.pdf) docs loader.load()LlamaIndex 那边也有类似的 Reader具体包名和导入路径建议以官方文档为准因为这类集成更新得比较快。如果你不想引额外的集成层更稳的做法就是我前面说的自己跑 docling拿到 Markdown 后再自己切分这样每一步都在掌控之内排查问题也方便。8.3 一条可以落地的处理管线最后分享一个我目前在生产环境里跑通的管线谈不上多高级但胜在每一步都看得见、出了问题都知道去哪查输入 PDF 后先用脚本判断文件有没有文本层有文本层直接 docling 转 Markdown关掉 OCR没有文本层先做页面增强再开启 OCR 转 Markdown导出对应的 JSON用来做表格校验和后续信息抽取对 Markdown 做清洗包括移除多余空行、修正表格分隔符、把图片替换成引用路径按标题层级切块保留标题作为块的元数据进 embedding 模型写入向量库。按照这个流程跑了几千份存量文档之后我的体会是docling 的输出质量大约决定了整个流程 70% 的上限但剩下 30% 还得靠自己的清洗和后处理。没有任何一个工具能像人一样完全理解版式复杂的文档docling 能做的是把“完全不可用”变成“基本可用”剩下的校对成本就要靠流程设计来压低了。