第 2 课

只转指定页、导出 JSON 与表格 CSV,用 Python API 定制转换

用页码范围只转第 3 到 5 页并同时导出 Markdown 与 JSON,看懂 DoclingDocument 里的文字类型与页脚;用 DocumentConverter 与 PdfPipelineOptions 关 OCR、保留表格识别,把表格导出成 CSV;再把官方安装文档 HTML 转成 Markdown。

图文25 分钟Docling 官方文档 ↗

课程目录第 2 / 3 课

学习位置仅保存在当前浏览器,有效期 180 天。

01 / 图文教材

只转指定页、导出 JSON 与表格 CSV,用 Python API 定制转换

本课对照的官方页面:CLI reference 、Export tables 示例 、Custom conversion 示例 、DoclingDocument 概念 、Supported formats 。测试环境同课时 1:2026-11-08,Linux x86_64 CPU,Python 3.12.15,docling 2.148.0。对照结果均为真实输出节选。

上一课把整份 PDF 转成了 Markdown。实际干活时,你常常只要其中几页,或者要拿到表格做分析、要保留每段文字来自第几页。本课先用命令行只转指定页、同时导出 JSON,再改用 Python API 把表格存成 CSV,最后顺手转一个 HTML 网页。

第 1 步:只转第 3 到 5 页,同时导出 Markdown 和 JSON

docling convert 的输出格式参数可以写多次,一次拿到多种格式:

docling convert 2408.09869.pdf --page-range 3-5 --no-ocr --image-export-mode placeholder --to md --to json --output out2
ls -lh out2

对照结果:

INFO  docling.document_converter: Finished converting document 2408.09869.pdf in 2.80 sec.

-rw-r--r-- 1 box box 90K Nov  8 00:09 2408.09869.json
-rw-r--r-- 1 box box 12K Nov  8 00:09 2408.09869.md

只处理 3 页,2.8 秒就完成了。页码从 1 开始数。

第 2 步:看 Markdown 里的表格

技术报告第 4 页有一张运行性能表(Table 1)。在输出里找表格行:

grep -n "^|" out2/2408.09869.md | cut -c1-120

对照结果:

51:| CPU                                         | Thread budget   | native backend - TTS   | native backend - Pages/s ...
52:|---------------------------------------------|-----------------|------------------------|-------------------------- ...
53:| Apple M3 Max                                | 4 16            | 177 s 167 s            | 1.27 1.34                ...
54:| (16 cores) Intel(R) Xeon E5-2690 (16 cores) | 4 16            | 375 s 244 s            | 0.60 0.92                ...

两层表头(native backend 和 pypdfium backend 下各有 TTS、Pages/s、Mem)被合并成了「native backend - TTS」这样的单层列名,这是 TableFormer 识别出的结构。原表里每台机器分 4 线程、16 线程两行,这里被合进了同一个单元格(「4 16」「177 s 167 s」),用之前要人工核一下。

第 3 步:JSON 里有什么

JSON 是 DoclingDocument 的无损序列化,比 Markdown 多了每个元素的类型、所在页码和坐标。用 Python 数一下:

python - <<'PY'
import json, collections
d = json.load(open("out2/2408.09869.json"))
print(d["schema_name"], d["version"])
print({k: len(v) for k, v in d.items() if isinstance(v, list)})
print(collections.Counter(t["label"] for t in d["texts"]))
PY

对照结果:

DoclingDocument 1.11.0
{'groups': 1, 'texts': 50, 'pictures': 1, 'tables': 1, 'key_value_items': 0, 'form_items': 0}
Counter({'text': 33, 'section_header': 10, 'page_footer': 3, 'caption': 2, 'list_item': 2})

注意 page_footer 被单独标了出来:转 Markdown 时页脚、页眉不会混进正文,这正是 Docling 和「直接抽文字」的区别。需要做引用溯源(回答出自第几页)时,就用 JSON。

第 4 步:改用 Python API,把表格存成 CSV

新建 convert_and_tables.py。写法综合了官方 Custom conversion 和 Export tables 两个示例:用 PdfPipelineOptions 关掉 OCR、保留表格结构识别,再用 export_to_dataframe 拿到 pandas 表格(pandas 已随 docling 安装)。

from pathlib import Path

from docling.datamodel.base_models import InputFormat
from docling.datamodel.pipeline_options import PdfPipelineOptions
from docling.document_converter import DocumentConverter, PdfFormatOption

SOURCE = "2408.09869.pdf"
OUT = Path("scratch")
OUT.mkdir(exist_ok=True)

opts = PdfPipelineOptions()
opts.do_ocr = False              # 电子版 PDF 不需要 OCR
opts.do_table_structure = True   # 表格结构识别保持开启

converter = DocumentConverter(
    format_options={InputFormat.PDF: PdfFormatOption(pipeline_options=opts)}
)
result = converter.convert(SOURCE, page_range=(1, 5))
doc = result.document
print("status:", result.status)
print("pages:", len(doc.pages), "tables:", len(doc.tables), "pictures:", len(doc.pictures))

(OUT / "report.md").write_text(doc.export_to_markdown(), encoding="utf-8")
doc.save_as_json(OUT / "report.json")

for i, table in enumerate(doc.tables, start=1):
    df = table.export_to_dataframe(doc=doc)
    df.to_csv(OUT / f"table-{i}.csv", index=False)
    print(f"table-{i}:", df.shape)

运行:

python convert_and_tables.py
ls -lh scratch
cat scratch/table-1.csv

对照结果:

status: ConversionStatus.SUCCESS
pages: 5 tables: 1 pictures: 2
table-1: (2, 8)

-rw-r--r-- 1 box box 120K Nov  8 00:10 report.json
-rw-r--r-- 1 box box  17K Nov  8 00:10 report.md
-rw-r--r-- 1 box box  334 Nov  8 00:10 table-1.csv

CPU.,Thread budget.,native backend.TTS,native backend.Pages/s,native backend.Mem,pypdfium backend.TTS,pypdfium backend.Pages/s,pypdfium backend.Mem
Apple M3 Max,4 16,177 s 167 s,1.27 1.34,6.20 GB,103 s 92 s,2.18 2.45,2.56 GB
(16 cores) Intel(R) Xeon E5-2690 (16 cores),4 16,375 s 244 s,0.60 0.92,6.16 GB,239 s 143 s,0.94 1.57,2.42 GB

几点对照说明:

  • page_range=(1, 5) 是 Python 写法,两端都包含,对应命令行里页码范围写成 1-5。
  • DataFrame 的列名用「.」连接两层表头(native backend.TTS),和 Markdown 里的「-」写法不同,但列数一致,都是 8 列。
  • 官方示例还演示了 table.export_to_html(doc=doc),想要保留合并单元格就导出 HTML。

第 5 步:转换 HTML 网页(以及 Word、PPT)

Docling 不只吃 PDF。Supported formats 页列出的输入包括 DOCX、PPTX、XLSX、HTML、Markdown、CSV、图片、LaTeX、EPUB 和邮件等,统一走同一个命令。下面把官方安装文档页面先存成 HTML 再转换:

curl -L -o installation.html https://docling-project.github.io/docling/getting_started/installation/
docling convert installation.html --to md --output out5
head -12 out5/installation.md

对照结果:

INFO  docling.document_converter: Finished converting document installation.html in 0.21 sec.

# Installation

To use Docling, simply install `docling` from your Python package manager, e.g. pip:

(后面紧跟的是代码块 pip install docling,原样保留。)HTML、DOCX 这类本身带结构的格式不需要跑版面模型,0.21 秒就完成了。Word 文件同理,换成你自己的 .docx 路径即可;本课测试机没有现成的 Word 文件,DOCX 未单独实测。

常见坑

  • 只想处理部分格式:用输入格式参数白名单,例如目录里混着 PDF 和图片、只转 PDF(见下方代码块)。
  • 批量转换:输入写成目录路径即可,Docling 会逐个转换。实测在一个同时放了 PDF 和 HTML 的目录上加 PDF 白名单,只生成了 PDF 对应的 Markdown,HTML 被跳过。
  • 表格要核对:多层表头、跨行单元格会被拍平,用于财报等严肃场景前请对照原文。
docling convert ./docs --from pdf --to md --output out-batch

小结

你学会了只转指定页、一次导出 Markdown 和 JSON,看懂了 DoclingDocument 的结构,并用 Python API 把表格存成了 CSV,还转了一个 HTML 页面。下一课把文档切成适合向量检索的块,并把 Docling 接成 MCP 工具给 AI 助手用。