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 = -1while page_chars[i].get('text').isspace():i = i - 1# print(page_chars[i].get('text'), i)return page_chars[i]# 返回列表最头部的非空字符
def head_not_space_char(page_chars):i = 0while page_chars[i].get('text').isspace():i += 1# print(page_chars[i].get('text'), i)return page_chars[i]# 将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)# 获取页面最底部非空字符的y0y0_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[3] - table_objects[-1].bbox[3])# 获取页面最顶部字符的y1y1_top_char.append(head_not_space_char(page.chars).get('y1'))# 获取页面最顶部表格中最底部字符的y1y1_top_table.append(page.bbox[3] - table_objects[0].bbox[1])print("1===========抽取每页顶部和底部字符坐标及表格文本结束===========1")# 处理跨页面表格,将跨页面表格合并,i是当前页码,对于连跨数页的表,应跳过中间页面,防止重复处理print("2===========开始处理跨页面表格===========2")i = 0while i < len(text_all_table):print("处理页面{0}/{1}".format(i+1, len(text_all_table)))# 判断当前页面是否以表格结尾且下一页面是否以表格开头,若都是则说明表格跨行,进行表格合并# j是要处理的页码,一般情况是当前页的下一页,对于连跨数页情况,也可以是下下一页,跨页数为k# 若当前页是最后一页就不用进行处理if i + 1 >= len(text_all_table):breakj = i + 1k = 1# 要处理的页为空时退出while text_all_table[j]:if y0_bottom_table[i] <= y0_bottom_char[i] and y1_top_table[j] >= y1_top_table[j]:# 当前页面最后一个表与待处理页面第一个表合并text_all_table[i][-1] = text_all_table[i][-1] + text_all_table[j][0]text_all_table[j].pop(0)# 如果待处理页面只有一个表,就要考虑下下一页的表是否也与之相连if not text_all_table[j] and j + 1 < len(text_all_table) and text_all_table[j + 1]:k += 1j += 1else:i += kbreakelse:i += kbreakprint("2===========处理跨页面表格结束===========2")# 保存excelprint("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[1:], columns=table[0])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[1:], columns=table[0])# 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)
方法也是修改csdn的一个大佬的 作者是吧跨页得都给弄成了一个个得excel 然后我给重新合并设置了序号 别的没加什么东西 大佬文章地址