在日常数据处理场景中,PDF格式的文件常常包含结构化的表格数据,手动提取这些内容不仅耗时,还容易出现格式错乱、数据丢失的问题。Python生态中的tabula-py库基于Java的Tabula工具开发,能够精准识别PDF中的表格内容,将其转换为DataFrame或者CSV、JSON等常见格式,大幅降低PDF表格处理的难度。

环境准备与安装
使用tabula-py前需要先完成环境配置,首先确保本地已经安装了Java运行环境,因为tabula-py依赖Java的Tabula核心功能。然后安装tabula-py库,执行以下命令即可:
# 安装tabula-py库 pip install tabula-py
安装完成后可以简单验证是否可用,导入库后如果没有报错说明安装成功:
import tabula
print("tabula-py库导入成功")
基础表格提取方法
tabula-py最常用的功能是read_pdf方法,该方法可以直接读取PDF中的表格,返回pandas的DataFrame对象,方便后续处理。以下是一个基础示例,提取单个PDF页面中的表格:
import tabula
import pandas as pd
# 读取PDF中的表格,指定PDF文件路径和要提取的页码
# pages参数可以指定单个页码,比如"1",也可以指定多个页码,比如"1,3,5"
df_list = tabula.read_pdf(
"sample.pdf", # PDF文件路径
pages="1", # 提取第1页的表格
multiple_tables=True # 当页面有多个表格时,返回所有表格
)
# df_list是DataFrame的列表,遍历输出每个表格的内容
for idx, df in enumerate(df_list):
print(f"第{idx+1}个表格内容:")
print(df)
提取结果保存为常见格式
提取到表格数据后,我们通常需要将其保存为更方便处理的格式,比如CSV、Excel或者JSON。tabula-py本身也提供了直接保存的功能,也可以结合pandas的存储方法实现:
直接保存为CSV
import tabula
# 直接提取PDF表格并保存为CSV文件
# output_format指定输出格式为csv,指定输出文件路径
tabula.convert_into(
"sample.pdf",
"output.csv",
output_format="csv",
pages="all" # 提取所有页面的表格
)
结合pandas保存为Excel
import tabula
import pandas as pd
# 读取所有页面的表格
df_list = tabula.read_pdf("sample.pdf", pages="all", multiple_tables=True)
# 将多个表格保存到同一个Excel文件的不同sheet中
with pd.ExcelWriter("output.xlsx") as writer:
for idx, df in enumerate(df_list):
df.to_excel(writer, sheet_name=f"表格{idx+1}", index=False)
常见场景处理技巧
提取指定区域的表格
如果PDF页面中有多个内容,只想提取特定区域的表格,可以使用area参数指定区域坐标,坐标格式为[top, left, bottom, right],单位是点(1点约等于1/72英寸):
import tabula
# 指定提取区域,比如提取页面顶部100点到底部500点,左侧50点到右侧500点的区域
df_list = tabula.read_pdf(
"sample.pdf",
pages="1",
area=[100, 50, 500, 500],
multiple_tables=True
)
print(df_list[0])
处理加密的PDF文件
如果PDF文件有密码保护,需要在读取时传入密码参数:
import tabula
# 传入PDF密码提取表格
df_list = tabula.read_pdf(
"encrypted_sample.pdf",
pages="1",
password="123456", # PDF文件的密码
multiple_tables=True
)
print(df_list[0])
提取后数据清洗
有时候提取到的表格可能存在空行、列名错位等问题,需要简单清洗后再使用。以下是常见的清洗操作示例:
import tabula
import pandas as pd
df_list = tabula.read_pdf("sample.pdf", pages="1", multiple_tables=True)
df = df_list[0]
# 删除全为空的行
df = df.dropna(how="all")
# 重置索引
df = df.reset_index(drop=True)
# 处理列名,如果第一行是表头但被识别为数据,可以调整
# df.columns = df.iloc[0] # 将第一行设为列名
# df = df[1:].reset_index(drop=True)
print("清洗后的表格:")
print(df)
注意事项
- tabula-py对扫描版的PDF支持较差,扫描版PDF需要先通过OCR工具转换为可编辑的文本PDF再提取
- 如果PDF中的表格线条不清晰,可能会出现单元格合并识别错误的情况,需要手动调整提取参数
- 确保Java环境版本在Java 8及以上,低版本Java可能导致tabula-py运行报错
- 处理大体积PDF文件时,建议逐页提取,避免一次性加载所有内容导致内存占用过高