python pdf跨页表格转换为excel
本帖最后由 whz1998 于 2024-5-17 01:18 编辑朋友让帮忙写个pdf转word的 但是里面涉及到跨页的表格,单纯读取转换好像不行 然后就百度写了个这玩意
~~~ python
import pdfplumber
import pandas as pd
import os
from openpyxl import load_workbook
from datetime import datetime
# page_chars最尾部的非空字符
def tail_not_space_char(page_chars):
i = -1
while page_chars.get('text').isspace():
i = i - 1
# print(page_chars.get('text'), i)
return page_chars
# 返回列表最头部的非空字符
def head_not_space_char(page_chars):
i = 0
while page_chars.get('text').isspace():
i += 1
# print(page_chars.get('text'), i)
return page_chars
# 将pdf表格数据抽取到文件中
def extract_tables(input_file_path, output_excel_path):
pdfList=[]
print("========================================表格抽取开始========================================")
# 读取pdf文件,保存为pdf实例
pdf = pdfplumber.open(input_file_path)
# 存储每个页面最底部字符的y0坐标
y0_bottom_char = []
# 存储每个页面最底部表格中最底部字符的y0坐标
y0_bottom_table = []
# 存储每个页面最顶部字符的y1坐标
y1_top_char = []
# 存储每个页面最顶部表格中最顶部字符的y1坐标
y1_top_table = []
# 存储所有页面内的表格文本
text_all_table = []
# 获取当前日期为转换后的文件名
current_datetime = datetime.now()
# 格式化为"YYYY-MM-DD HH:MM:SS"的字符串
formatted_datetime = current_datetime.strftime("%Y-%m-%d %H-%M-%S")
fileName=formatted_datetime+".xlsx"
# print("格式化后的日期时间:", formatted_datetime)
# 访问每一页
print("1===========开始抽取每页顶部和底部字符坐标及表格文本===========1")
for page in pdf.pages:
# table对象,可以访问其row属性的bbox对象获取坐标
table_objects = page.find_tables()
text_table_current_page = page.extract_tables()
if text_table_current_page:
text_all_table.append(text_table_current_page)
# 获取页面最底部非空字符的y0
y0_bottom_char.append(tail_not_space_char(page.chars).get('y0'))
# 获取页面最底部表格中最底部字符的y0,table对象的bbox以左上角为原点,而page的char的坐标以左下角为原点,可以用page的高度减去table对象的y来统一
y0_bottom_table.append(page.bbox - table_objects[-1].bbox)
# 获取页面最顶部字符的y1
y1_top_char.append(head_not_space_char(page.chars).get('y1'))
# 获取页面最顶部表格中最底部字符的y1
y1_top_table.append(page.bbox - table_objects.bbox)
print("1===========抽取每页顶部和底部字符坐标及表格文本结束===========1")
# 处理跨页面表格,将跨页面表格合并,i是当前页码,对于连跨数页的表,应跳过中间页面,防止重复处理
print("2===========开始处理跨页面表格===========2")
i = 0
while i < len(text_all_table):
print("处理页面{0}/{1}".format(i+1, len(text_all_table)))
# 判断当前页面是否以表格结尾且下一页面是否以表格开头,若都是则说明表格跨行,进行表格合并
# j是要处理的页码,一般情况是当前页的下一页,对于连跨数页情况,也可以是下下一页,跨页数为k
# 若当前页是最后一页就不用进行处理
if i + 1 >= len(text_all_table):
break
j = i + 1
k = 1
# 要处理的页为空时退出
while text_all_table:
if y0_bottom_table <= y0_bottom_char and y1_top_table >= y1_top_table:
# 当前页面最后一个表与待处理页面第一个表合并
text_all_table[-1] = text_all_table[-1] + text_all_table
text_all_table.pop(0)
# 如果待处理页面只有一个表,就要考虑下下一页的表是否也与之相连
if not text_all_table and j + 1 < len(text_all_table) and text_all_table:
k += 1
j += 1
else:
i += k
break
else:
i += k
break
print("2===========处理跨页面表格结束===========2")
# 保存excel
print("3===========开始保存表格到excel===========3")
for page_num, page in enumerate(text_all_table):
for table_num, table in enumerate(page):
print("处理表格页面{0}/表格{1}".format(page_num, table_num))
if table:
table_df = pd.DataFrame(table, columns=table)
final_filename = output_excel_path + "page{0}_table{1}.xlsx".format(page_num, table_num)
table_df.to_excel(final_filename)
print("生成文件:", final_filename)
pdfList.append(final_filename)
print("3===========保存表格到excel结束===========3")
print("4===========开始合并excel===========4")
# print(pdfList)
# 合并所有Excel文件
all_data = []
for file in pdfList:
file_path = os.path.join(file)
df = pd.read_excel(file_path)
all_data.append(df)
# 合并数据帧
combined_df = pd.concat(all_data, ignore_index=True)
# 保存到新的Excel文件
combined_df.to_excel(fileName, index=False)
wb = load_workbook(fileName)
sheet = wb.active
# 获取"A"列的范围
column = sheet['A']
# 生成序号并写入"A"列
for i, cell in enumerate(column, start=0):
cell.value = i
# 保存修改后的Excel文件
wb.save(fileName)
print("5===========合并excel结束===========5")
for file in pdfList:
os.remove(file)
# # 保存txt
# print("4===========开始保存表格到txt===========4")
# for page_num, page in enumerate(text_all_table):
# for table_num, table in enumerate(page):
# print("处理表格页面{0}/表格{1}".format(page_num, table_num))
# if table:
# table_df = pd.DataFrame(table, columns=table)
# final_filename = output_excel_path + "page{0}_table{1}.txt".format(page_num, table_num)
# with open(final_filename,"w") as f:
# f.write(table_df.to_string())
# f.close()
# # print("生成文件:", final_filename)
# print("4===========保存表格到txt结束===========4")
# print("========================================表格抽取结束========================================")
if __name__ == '__main__':
# 抽取表格
input_file = "pdf.pdf"
output_excel_path = ""
extract_tables(input_file, output_excel_path)
~~~
还有点问题 最后那个分数 小数点后面四舍五入了 但是他这个不咋需要 就没改
成品我稍微修改一下放到百度云盘了 有点大 大概50m需要手动输入文件名 后缀也要写,文件要和这个软件放到同一个文件夹下面
链接:https://pan.baidu.com/s/120UjWGDMRCs5jkFMObAzQA?pwd=j1rg
提取码:j1rg
zylz9941 发表于 2024-5-16 10:16
楼主:麻烦发个成品嘛
等晚点我打个包放上去吧 这是保存到 word 还是 Excel 呀?最后两张图片有啥区别呀? Arcticlyc 发表于 2024-5-16 00:32
这是保存到 word 还是 Excel 呀?最后两张图片有啥区别呀?
最后两个图上传重复了,保存成excel写错了 不好意思 whz1998 发表于 2024-5-16 00:34
最后两个图上传重复了,保存成excel写错了 不好意思
嗷嗷,这是可以提取出 pdf 中跨页的表格吗? Arcticlyc 发表于 2024-5-16 00:37
嗷嗷,这是可以提取出 pdf 中跨页的表格吗?
是的 就那个数据有点问题 精确到多少位之后 就开始四舍五入了 我没改 不错啊,高手 小白请教,代码咋运行啊? 学习学习!!! 程序逻辑上没毛病,但这么写的话,在实际处理过程中一定会出错。 佩服佩服