脚本专家 发表于 5 天前

Python用Spire.PDF提取PDF表格并导出CSV教程

PDF 里的表格和 Excel 表格并不是同一种数据。PDF 文件通常不保存结构化表格,页面上的行与列只是文字、线条按坐标呈现出来的视觉效果。因此,用脚本读取 PDF 表格,本质上是通过库分析页面版式,再还原行列结构。

一、环境准备

安装 Spire.PDF:


pip install Spire.PDF


如果只是学习或处理小文档,也可以使用免费版本:


pip install Spire.Pdf.Free


免费版在加载和处理 PDF 时有页数限制,最多处理前 10 页。超过 10 页的文档需要先拆分,或改用完整版 PyPI。

二、核心提取代码

下面代码演示加载 PDF、逐页提取表格,并按行输出单元格文本:


from spire.pdf import PdfDocument, PdfTableExtractor

# 加载 PDF 文档
pdf = PdfDocument()
pdf.LoadFromFile("input.pdf")

# 创建表格提取器
table_extractor = PdfTableExtractor(pdf)

# 逐页提取表格
for i in range(pdf.Pages.Count):
    tables = table_extractor.ExtractTable(i)
    for table_index, table in enumerate(tables):
      print(f"Table {table_index + 1} on page {i + 1}:")
      for row in range(table.GetRowCount()):
            row_data = []
            for col in range(table.GetColumnCount()):
                text = table.GetText(row, col).replace("\n", " ")
                row_data.append(text.strip())
            print("\t".join(row_data))


三、关键步骤说明

1. 加载 PDF 文档

PdfDocument 是文档入口对象,LoadFromFile() 接收 PDF 路径,相对路径和绝对路径都可以。

2. 创建表格提取器

PdfTableExtractor 用来对文档逐页分析版式并检测表格结构,构造时需要传入已经加载的 PdfDocument 对象。

3. 逐页提取表格

pdf.Pages.Count 表示总页数,ExtractTable(i) 返回第 i 页检测到的所有表格。它返回的是列表,因为一页中可能有多个表格;如果该页没有表格,则返回空列表。

4. 遍历行列读取单元格

GetRowCount() 和 GetColumnCount() 分别获取行数、列数;GetText(row, col) 读取指定单元格文本。单元格内可能包含换行,代码先把 \n 替换为空格,再 strip() 去掉首尾空白,避免输出多余空行。最后用制表符 \t 拼接一行单元格,方便复制到 Excel 或作为 TSV 使用。

四、运行效果

对一份包含简单表格的 PDF 运行上述代码,控制台输出大致如下:


Table 1 on page 1:
姓名    部门    薪资
张三    技术部    12000
李四    市场部    9800
王五    财务部    10500


每行对应表格中的一行,单元格之间由制表符分隔,可以直接粘贴到表格软件。

五、进阶:保存为 CSV

如果不想只打印到控制台,可以用 Python 内置 csv 模块写入 CSV,不需要额外安装库:


import csv
from spire.pdf import PdfDocument, PdfTableExtractor

pdf = PdfDocument()
pdf.LoadFromFile("input.pdf")
extractor = PdfTableExtractor(pdf)

with open("output.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    for i in range(pdf.Pages.Count):
      for table in extractor.ExtractTable(i):
            for row in range(table.GetRowCount()):
                row_data = [
                  table.GetText(row, col).replace("\n", " ").strip()
                  for col in range(table.GetColumnCount())
                ]
                writer.writerow(row_data)

pdf.Close()


csv.writer 会自动处理单元格中的逗号、引号等特殊字符,通常比手动拼接字符串更可靠。批量处理完成后,建议调用 pdf.Close() 释放资源。

六、注意事项与局限

1. 更适合有清晰边框的表格。PdfTableExtractor 依赖页面版式分析,对边框明确、结构规整的表格识别效果较好;无可见边框、多行单元格或表头不明确的复杂排版,可能出现检测不到或结构不完整。

2. 扫描件需要先 OCR。如果 PDF 是扫描图片、没有文本层,文本类工具无法直接读取内容,需要先用 OCR 把图片转成文字,Spire.PDF 本身不提供 OCR。

3. 免费版页数限制。免费版最多处理前 10 页,长文档可以在循环里使用 min(pdf.Pages.Count, 10) 限制,或先按页拆分。

4. 资源释放。批量处理大量文件时,最后调用 pdf.Close(),避免资源占用。

七、其他可选库

如果遇到 Spire.PDF 处理不了的复杂表格,可以尝试以下开源库作为补充:

pdfplumber:基于 pdfminer.six,提供较细粒度的页面对象访问,适合复杂排版。
camelot:通过检测表格线识别结构,对有线表格效果较好。
tabula-py:封装 Java 的 tabula,输出可直接兼容 pandas DataFrame。

实际项目中可以按表格类型组合使用:结构规整的表格任选一个库即可,复杂表格建议先小样本测试再选型。

八、总结

用 Spire.PDF for Python 提取 PDF 表格的流程是:加载文档,创建 PdfTableExtractor,逐页调用 ExtractTable(),再遍历行列读取单元格。它适合边框清晰、结构规整的表格,配合 csv 模块即可落盘保存。遇到无边框、扫描件等情况,则需要 OCR 或其他 PDF 解析库配合。

热心网友3 发表于 5 天前

Re: Python用Spire.PDF提取PDF表格并导出CSV教程

楼主这篇教程挺完整的,从原理到代码再到 CSV 导出都覆盖到了。以前我一直以为 PDF 表格可以直接像 Excel 一样读,看了开头解释才明白它只是坐标上的视觉排版,必须靠库去还原行列结构,这个点讲得很清楚。 代码部分很实用,逐页 ExtractTable、再遍历行列 GetText,最后用制表符输出,复制到 Excel 很方便。进阶里用 csv.writer 处理逗号和引号确实更稳妥。注意事项也很到位,特别是免费版 10 页限制、扫描件要先 OCR、批量处理完调用 pdf.Close(),这些都是实际跑脚本时容易踩的坑。 如果遇到复杂表格,我也会按你提到的 pdfplumber、camelot、tabula-py 去补充尝试。感谢分享,收藏了。

热心网友4 发表于 5 天前

Re: Python用Spire.PDF提取PDF表格并导出CSV教程

感谢分享,写得很清楚。PDF 表格不是结构化数据这个前提很重要,不然很多人会以为直接读就能拿到行列。ExtractTable 这套思路对边框清晰的表格确实实用,CSV 那段也比只打印到控制台更完整。实际用的时候我会额外加两列:来源页码和表格序号,后面核对数据方便;中文 CSV 如果用 Excel 打开乱码,可以试 utf-8-sig。免费版 10 页限制和最后 Close 释放资源这两个提醒很关键,批量处理时容易忽略。扫描件和复杂无边框表格确实不能硬靠文本提取,先 OCR 或换 pdfplumber、camelot、tabula-py 这类库比较稳妥。整体很适合入门,收藏了。

热心网友2 发表于 5 天前

Re: Python用Spire.PDF提取PDF表格并导出CSV教程

感谢分享,这篇写得很清楚。以前确实容易把 PDF 表格当成 Excel 那种结构化数据,开头那段解释很到位。代码里把单元格里的换行先替换成空格再 strip,这个细节很实用,不然导 CSV 时很容易一行变多行。 另外你提到的几个坑也很关键:免费版最多处理前 10 页、扫描件要先 OCR、批量处理完调用 pdf.Close() 释放资源。这些对刚开始用的人很有帮助。 有个小疑问:如果一页里有多个表格,CSV 示例会把它们按顺序写到同一个文件里,没有页码或表序号区分。实际用的时候是不是最好自己加一列来源信息?复杂表格再考虑 pdfplumber 之类的补充方案,这个思路也记下了。
页: [1]
查看完整版本: Python用Spire.PDF提取PDF表格并导出CSV教程