python读取pdf表格并合并为excel

news/2024/9/23 20:11:30/
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 = -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 然后我给重新合并设置了序号 别的没加什么东西 大佬文章地址


http://www.ppmy.cn/news/1437965.html

相关文章

HCIP-Datacom-ARST必选题库_01_ACL【7道题】

一、单选 1.下面是一台路由器的部分配置,关于该配置描述正确的是&#xff1a; 源地址为1.1.1.1的数据包匹配第一条ACL语句rule 0,匹配规则为允许 源地址为1.1.1.3的数据包匹配第三条ACL语句rule 2,匹配规则为拒绝 源地址为1.1.1.4的数据包匹配第四条ACL语句rule 3,匹配规则为允…

头歌Java实验面向对象高级

第1关&#xff1a;类的继承和super关键字 package step1;class Animal{String name;public void shout(){System.out.println(this.name "发出叫声");}public Animal(String name) {this.name name;} }// ---------------------Begin------------------------ //编…

C++及QT的线程学习

目录 一. 线程学习 二. 学习线程当中&#xff0c;得到的未知。 1. 了解以下MainWindow和main的关系 2. []()匿名函数 有函数体&#xff0c;没有函数名. 3. join和detach都是用来管理线程的生命周期的&#xff0c;它们的区别在于线程结束和资源的回收。 4. operator()() 仿…

深度学习每周学习总结P5(运动鞋识别)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 –来自百度网盘超级会员V5的分享 数据链接 提取码&#xff1a;9539 目录 0. 总结1. 数据导入及处理部分2. 加载数据集3.模型构建部分3.1…

问答机器人学习资料

longchain 5 分钟内搭建一个免费问答机器人&#xff1a;Milvus LangChain-腾讯云开发者社区-腾讯云 chatglm大模型 基于本地知识的问答机器人langchain-ChatGLM 大语言模型实现方法详解_python_脚本之家 探索QRobot&#xff1a;智能对话与聊天机器人的开源奇缘-CSDN博客 如何…

Python爬虫(入门版)

1、爬虫是什么 简单的来说&#xff1a;就是用程序获取网络上数据。 2、爬虫的原理 如果要获取网络上数据&#xff0c;我们要给爬虫一个网址&#xff08;程序中通常叫URL&#xff09;&#xff0c;爬虫发送一个HTTP请求给目标网页的服务器&#xff0c;服务器返回数据给客户端&am…

kotlin根据文件的filePath转化为uri

方法实现 使用File类来创建一个文件对象&#xff0c;然后通过FileProvider来获取文件的URI import android.content.Context import android.net.Uri import androidx.core.content.FileProvider import java.io.Filefun getFileUri(context: Context, filePath: String): Ur…

1分钟掌握 Python 函数参数

任何编程语言函数都是非常重要的一部分&#xff0c;而在进行函数调用时&#xff0c;了解函数的参数传递方式是非常有必要的。Python中支持哪些传参方式呢&#xff1f; Python中的传参方式是比较灵活的&#xff0c;主要包括以下六种&#xff1a; 按照位置传参按照关键字传参默…