Docling 提取 PDF 表格:导出 CSV 后,怎样查错列和合并单元格

用一份两页练习报价单,导出结构JSON、Markdown预览和逐表CSV,再按原页核对金额、单位与合并单元格。附防覆盖Python脚本、AI对照提示词和失败处理说明。

PDF 里明明只有两列价格,导出后总金额还对,单价却落进了“数量”列。把 CSV 交给 AI 润色,错误可能变得更像一张正式报表。用 Docling 提取表格时,值得建立的是一份能回看原页的核对材料,而不是直接接入商品库或财务系统。

下面从 Windows 本地练习开始,只处理一份两页 PDF,输出 Markdown、结构 JSON 和逐表 CSV。适合要批量处理报价单、产品目录的运营,也适合为知识库准备数据的开发者。本文核对了官方接口,并对自写脚本做了 14 项内存替身检查;没有安装 Docling、运行 OCR 或转换真实 PDF,不能据此声称识别准确率。

练习文件要能看出错列,不能只有一排数字

在自己的文档软件里做一份无敏感信息的两页练习材料并导出 PDF,命名为 sample.pdf。第一页放表格,列为 SKU、品名、数量、单价、金额:AX001、Cup、3、19.90、59.70;AX002、Plate、2、45.00、90.00,合计 149.70。第二页写“币种 CNY,价格含税,编号保留原样”。这些是人为设定的核对基准,不是本站提取出的结果。

再给表格加一个跨列标题“示例报价”。它能帮助暴露合并单元格在导出后的变化。不要把原件唯一副本当输入,也不要拿未获授权的客户报价测试。保留 PDF 页码,纸面脚注的币种和税务口径即使不在表格里,也不能丢。

选用 Docling,是为了保留检测到的文档结构并逐表导出,而不是让聊天模型猜表格。代码开源、本地处理不按页向厂商买额度,但计算、存储和模型下载仍有成本;模型本身的授权另查。只处理偶尔一页时,人工复制再核对也可能更省事。

Windows 环境放在独立文件夹,不改系统 Python

准备 Python 3.10 或更新的兼容版本,在一个新建的练习文件夹打开 PowerShell。这里固定 Docling 2.145.0,避免未来默认安装的新版本改变接口;这不是保证任意 Python、显卡或驱动组合都能安装。先按官方安装文档核对自己的环境。

python -m venv .venv
& .\.venv\Scripts\python.exe -m pip install "docling==2.145.0" pandas

直接调用虚拟环境里的解释器,不需要修改 PowerShell 执行策略或全局依赖。安装报错就先记录 Python 版本和完整错误,不要跟着 AI 使用管理员权限重装系统包。公司电脑应遵守软件安装政策。

模型可能在首次运行时联网下载;“本地执行”不等于首次启动就完全离线。隔离网络环境应先按官方离线说明准备依赖和权重。本文不启用远程服务或第三方插件,也不要求输入云端 API 密钥;另加远程模型、插件或 URL 输入后,要重新确认数据会去哪里。

一次导出三种材料,已有目录就停止

把下面内容保存为 export_review.py,与 sample.pdf 放在一起。它限制到第 1—2 页;没有检测到表格就报错,输出目录已存在也不覆盖。它只是初步提取,不负责把每一张表解释成业务字段。

import json
from pathlib import Path
from docling.document_converter import DocumentConverter

def export_review(source=Path("sample.pdf"), out=Path("export-review")):
    if not source.is_file() or source.suffix.lower() != ".pdf":
        raise ValueError("Provide a local sample.pdf")
    if out.exists():
        raise FileExistsError("Output already exists; choose a new directory")
    result = DocumentConverter().convert(source, page_range=(1, 2))
    doc = result.document
    if not doc.tables:
        raise RuntimeError("No tables detected; inspect the source pages")
    out.mkdir()
    (out / "document.json").write_text(
        json.dumps(doc.export_to_dict(), ensure_ascii=False, indent=2),
        encoding="utf-8",
    )
    (out / "preview.md").write_text(
        doc.export_to_markdown(), encoding="utf-8"
    )
    for number, table in enumerate(doc.tables, start=1):
        table.export_to_dataframe(doc=doc).to_csv(
            out / f"table-{number:02d}.csv",
            index=False,
            encoding="utf-8-sig",
        )
    print(f"Exported {len(doc.tables)} detected tables. Review required.")

if __name__ == "__main__":
    export_review()

在同一文件夹执行 & .\.venv\Scripts\python.exe .\export_review.py。如果成功,export-review 中应有 preview.md、document.json 和按检测顺序编号的 CSV。编号不是 PDF 页码,也不是业务表名;真实检测表数可能与肉眼看到的不同。脚本没有承诺只有一张表,更不会自动把跨页表拼成一张。

14 项检查只验证语法、控制流、文件命名、导出参数和拒绝覆盖等路径,使用的是内存替身。真实包导入、模型下载、表格检测与文件转换仍需在你的环境验证。看到“Exported”也只表示导出流程走完,不表示数据通过验收。

Markdown 空了一格,先回到结构和原页

Markdown 表格没有合并单元格的表达能力。Docling 的序列化说明指出,跨行跨列信息在 Markdown 中会被展平,被覆盖位置可能显示为空;JSON 或 HTML 更适合查看检测到的合并结构。因此,空白不一定是漏识别,也不能反过来假定每个空格都继承上一行。

打开原 PDF,对照 CSV 查 AX001 和 AX002 各自的品名、数量、单价、金额,再看币种及含税脚注。核算 3×19.90=59.70、2×45.00=90.00、合计149.70。合计匹配仍不能证明列都对:错列、重复行或缺行有时也会碰巧抵消。

JSON 保留的是 Docling 已检测到的结构,不是对原始页面的真实性担保。OCR 可能把 O 和 0、负号和短横线识别错,编号前导零也可能在后续表格软件里被改掉。CSV 使用 UTF-8 BOM 是为了兼顾常见软件读中文,不能修复这些语义错误。

交给 AI 的是一份对照任务,不是自动补表许可

只摘取有权分享的几行,并附上人工核对的原页字段。可以让你已有的 Claude 等工具列差异;账号额度和上传政策按所用服务核实,不要求购买新套餐,也不要把整份商业文件当成默认输入。

你只核对给定信息,不联网,不补字段。
人工原页记录:AX001,Cup,数量3,单价19.90,金额59.70;
AX002,Plate,数量2,单价45.00,金额90.00;
合计149.70,币种CNY,含税。
下面另附提取结果。
按SKU比较品名、数量、单价、金额及缺行、重复行。
输出:原页值、提取值、匹配或冲突、需要人工检查的位置。
空白、跨页或合并单元格不自行推断;缺证据写“待查”。
不得直接生成可导入生产系统的修正版。

模型指出差异后,人再回到相应原页确认。原页本身不清楚,就记待查,不让模型按常识补一个价格。需要改正的数据另存审核版本,保留原提取件及修改理由,避免第二个人看不到错误从哪里来。

没有表、目录已存在、中文不对,各有处理办法

没有检测到表格时,先确认练习的两页确实有目标表,文件不是损坏或加密状态,再查看日志与 OCR 配置。若为中文扫描件,按官方 OCR 文档选择对应引擎及语言模型;不要仅换一个提示词就宣布解决。文字可选中的 PDF 也可能有错乱的阅读顺序。

目录已存在说明防覆盖检查生效。先查看里面是否为上次成功结果或失败中间件,保留排查资料;确认后换一个新的输出目录名,而不是让 AI 自动递归删除。导出中途失败可能留下部分文件,这些不能一起标成成功。

CSV 在表格软件里显示异常时,先检查编码和导入列类型;SKU、长编号按文本处理,金额、日期和千分位分别核对。不要只靠双击打开后的显示判断原文件,也不要对所有空格一键填充、对所有相同 SKU 一键去重。

交付时附一张核对状态表

  • 注明源文件版本、处理页范围、Docling 版本和处理日期。
  • 保留原 PDF、结构 JSON、预览和原始 CSV,不覆盖业务原表。
  • 每张表标明对应原页,记录表头、单位、合并单元格、缺行和重复行的检查结果。
  • 把已核对、冲突、待查分开;只有明确审核通过的数据才进入下一步。
  • 确认接收人知道这些是提取结果,不是已获业务批准的入库文件。

可进一步查阅官方逐表导出示例和序列化说明。当一张表无法解释清楚时,停在待查比交出一份“看起来完整”的 CSV 更可靠。

本文由 AI Islands 根据产品官网及公开资料独立整理。工具功能和价格可能变化,请以官网最新信息为准。