Python PDF文件合并,提取
admin
2024-02-06 16:45:09
0

文章目录

  • 1. 功能介绍
  • 2.项目难点
    • 1. tkinter设置图标显示
  • 3. 源代码
  • 3. 代码打包
    • 1. 打包过后程序运行出错
    • 2. 打包命令
    • 3.打包技巧

1. 功能介绍

  1. 选择两个pdf指定的页码并合并成一个文
  2. 选择一个指定的pdf文件,并指定页码,将指定的页码提取出来,可以用’,‘和’-‘分割
  3. 选择一个pdf文件,将其内容转换为word文件。
  4. 选择一个pdf文件将其表格转换为excel文件

2.项目难点

1. tkinter设置图标显示

tkinter设置图标显示可以使用TK.iconbitmap(‘pdf.ico’)函数实现。
但是在打包成一个exe文件之后,就无法实现了。
可以将ico文件通过base64模块的base64decode()将ico文件转换成数据流,然后创建一个新的py文件来保存成一个参数。如此在使用过程中通过再将base64数据转换成一个ico文件,再引用即可。

import base64open_icon = open("image/pdf.ico", "rb")
b64str = base64.b64encode(open_icon.read())
open_icon.close()
write_data = "img = %s" % b64str
# write_data = b64str
with open("icon.icon", "w+") as f:f.write(write_data)

引用base64数据,生成一个ico文件并在系统中引用

import ctypes
import tkinter as tk
import base64
import os
from icon import imgif __name__ == "__main__":# 以下两句代码用于将windows的任务栏图标设置为跟程序icon一样。myappid = "company.product.version"  # 这里可以设置任意文本ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)window = tk.Tk()window.title = "testicon"window.geometry("800x400")window.resizable(0, 0)img_data = base64.b64decode(img)with open("pdf.ico", "wb+") as fw:fw.write(img_data)window.iconbitmap("pdf.ico")os.remove("pdf.ico")window.mainloop()

3. 源代码

#!python
# author:kunta
# date: 2022-09
# version 1.1.0
# description: this software have 4 function
# 1. 选择两个pdf指定的页码并合并成一个文件,未指定页码则完全合并两个文件
# 2. 选择一个指定的pdf文件,并指定页码,将指定的页码提取出来,可以用’,‘和’-‘分割
# 3. 选择一个pdf文件,将其内容转换为word文件。
# 4. 选择一个pdf文件将其表格转换为excel文件。# date 2022-10
# version 2.0
# 本版本增加PDFOCR识别功能。import tkinter as tk
from tkinter import ttk, HORIZONTAL
from tkinter import filedialog
from tkinter import messagebox
from tkinter import Button, Label, StringVar, IntVar
from tkinter.ttk import Separator
from tkinter import RAISED
from PyPDF2 import PdfReader, PdfMerger, PdfWriter
from functools import partial
from pdf2docx import Converter
import pdfplumber as ppm
import pandas as pd
import ctypes
from icon import img   # 将pdf.ico图片转换成base64文件并作为img变量保存到icon.py中。
import openpyxl
import cv2
import os
import base64# 读取合并文件的第一个选择框内容
def askfile1():# 打开文件选择器,并筛选出pdf文件filename = tk.filedialog.askopenfilename(filetypes=[('PDF', '*.pdf'), ('All Files', '*')])if filename is None:entry1.insert(0, '您没有选择任何文件!')else:entry1.delete(0, "end")     # 选择文件之后,将entry1输入框的内容清空。entry1.insert(0, filename)  # 然后将选择的文件全路径插入到entry1输入框中# 读取合并文件的第二个选择框内容
def askfile2():filename = tk.filedialog.askopenfilename(filetypes=[('PDF', '*.pdf'), ('All Files', '*')])if filename is None:entry2.insert(0, '您没有选择任何文件!')else:entry2.delete(0, "end")entry2.insert(0, filename)# 读取分割文件选择框内容
def askfile3():filename = tk.filedialog.askopenfilename(filetypes=[('PDF', '*.pdf'), ('All Files', '*')])if filename is None:entry3.insert(0, '您没有选择任何文件!')else:entry3.delete(0, "end")entry3.insert(0, filename)# 读取pdf转word选择框内容
def askfile4():filename = tk.filedialog.askopenfilename(filetypes=[('PDF', '*.pdf'), ('All Files', '*')])if filename is None:entry4.insert(0, '您没有选择任何文件!')else:entry4.delete(0, "end")entry4.insert(0, filename)# 读取pdf转Excel选择框内容
def askfile5():filename = tk.filedialog.askopenfilename(filetypes=[('PDF', '*.pdf'), ('All Files', '*')])if filename is None:entry5.insert(0, '您没有选择任何文件!')else:entry5.delete(0, "end")entry5.insert(0, filename)# 将两个pdf文件进行合并
def pdfmerger():# print(filename)filename1 = entry1.get()filename2 = entry2.get()file1 = PdfReader(filename1)file2 = PdfReader(filename2)mergerfile = PdfMerger()# 如果用户输入的正确的页码范围,则合并用户输入的页码范围,如果用户输入的页码范围不正确,则将两个文件完全合并try:page11 = int(entry11.get()) - 1page12 = int(entry12.get())page21 = int(entry21.get()) - 1page22 = int(entry22.get())if page11 < 0 or page12 < 0 or page21 < 0 or page22 < 0 or page11 > page12 or page21 > page22 or page12 > len(file1.pages) or page22 > len(file2.pages):messagebox.showerror(title='错误消息', message="请输入正确的页码")returnmergerfile.append(file1, pages=(page11, page12))mergerfile.append(file2, pages=(page21, page22))except:mergerfile.append(file1)mergerfile.append(file2)with open('merger.pdf', 'wb') as outputstream:mergerfile.write(outputstream)messagebox.showinfo(title='文件合并完成', message="文件合并完成,合并后文件名称为msrger.pdf")# print(test1)# 将pdf文件的内容页面进行提取
def pdfspilit():filename = entry3.get()page31 = entry31.get()# page32 = int(entry32.get())file3 = PdfReader(filename)pagelist = []pages = page31.replace(" ", "").split(",")# pages.pop()print("pages:", pages)for i in pages:if i.isdigit():pagelist.append(int(i))else:if i == "":breakrep1 = i.replace('-', ",")rep2 = rep1.split(",")# i = list(i)print("i:", i)for j in range(int(rep2[0]), int(rep2[1])+1):pagelist.append(int(j))print("pagelist:", pagelist)# pages = list(pages)spilitfile = PdfWriter()# spilitfile.append(file3, pages=(page31, page32))pagelist = list(set(pagelist))for i in pagelist:i = i-1spilitfile.addPage(file3.getPage(i))with open('split.pdf', 'wb') as outputstream:spilitfile.write(outputstream)messagebox.showinfo(title="文件提取完成", message="提取后的文件名称为 split.pdf")# 定义一个函数用来将pdf文件转换为word
def pdftoword():filename = entry4.get()convert = Converter(filename)try:convert.convert('pdf2work.docx', start=0, end=None)convert.close()messagebox.showinfo(title="PDF文件转换完成", message='PDF文件转换完成,文件保存为pdf2word.docx')except:messagebox.showerror(title='PDF文件转换失败', message='PDF文件转换失败,请检查源文件')# 定义一个函数用以将pdf转换为excel
def pdftoexcel():filename = entry5.get()items = []startpage = int(entry51.get()) - 1endpage = int(entry52.get())with ppm.open(filename) as pdf:for page in range(startpage, endpage):try:table = pdf.pages[page].extract_table()for line in table:items.append(line)except:messagebox.showerror(title='文件转换失败', message="文件转换失败,请选择正确的文件或者要转换的页码")returnif len(items) == 0:messagebox.showerror(title="未读取到表格信息", message="未读取到表格信息,请选择正确的文件或页码")else:# head = items[0]# print(head)# items.pop(0)print(items)# df = pd.DataFrame(items, columns=head)df = pd.DataFrame(items)df.to_excel('excel.xlsx', index=False)messagebox.showinfo(title="PDF转Excel完成", message="PDF转Excel完成,文件保存为excel.xlsx")if __name__ == '__main__':# 以下两句代码用于将windows的任务栏图标设置为跟程序icon一样。myappid = "company.product.version"  # 这里可以设置任意文本ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)# create tkinter instancewindow = tk.Tk()# add a title towindow.title('英纳法重庆公司PDF文件合并/提取及转换工具')# set the windows size and cannot resize the windowwindow.geometry('830x430')window.resizable(0, 0)# 将img参数转换成图片,并设置为程序图标img_data = base64.b64decode(img)with open("pdf.ico", "wb+") as fw:fw.write(img_data)window.iconbitmap("pdf.ico")os.remove("pdf.ico")# 定义文件名参数,用于在选择文件之后,显示文件名到后面的输入框中。filename1 = StringVar()filename2 = StringVar()filename3 = StringVar()filename4 = StringVar()filename5 = StringVar()path = tk.StringVar()# 读取PDF合并的第一个文件btn = tk.Button(window, text='选择第一个文件', command=askfile1)   # 第一个btn按钮,调用askfile1程序,打开读取文件,并将值传递给entry1btn.grid(row=0, column=0)  # 通过grid进行布局,将btn布局到第一行第一列。entry1 = tk.Entry(window, textvariable=filename1)   # 定义一个Entry控件,其值为fliename1.entry1.grid(row=0, column=1, columnspan=3, ipadx=160)  # 将entry1布局到第一行第二列,跨行3,宽度设置为160.entry11 = tk.Entry(window)  # 定义一个输入框用来设置第一个文件的起始页entry11.grid(row=0, column=5)entry11.insert(0, '起始页')  # 给Enrtry11设置一个初始值‘起始页’,entry12 = tk.Entry(window)  # 定义一个输入框用来设置第一个文件的最后一页entry12.grid(row=0, column=6)entry12.insert(0, '结束页')# 读取PDF合并的第二个文件btn2 = tk.Button(window, text='选择第二个文件', command=askfile2)btn2.grid(row=1, column=0)entry2 = tk.Entry(window, textvariable=filename2)entry2.grid(row=1, column=1, columnspan=3, ipadx=160)entry21 = tk.Entry(window)entry21.grid(row=1, column=5)entry21.insert(0,'起始页')entry22 = tk.Entry(window)entry22.grid(row=1, column=6)entry22.insert(0, '结束页')# 定义一个BTN,点击执行pdf文件合并功能。mergerBtn = tk.Button(window, text='合并文件', command=partial(pdfmerger))mergerBtn.grid(row=2, column=0)# 定义一个分割线,用来分开两个功能,sticky指示线的方向sep = Separator(window, orient=HORIZONTAL)sep.grid(row=3, column=0, columnspan=8, padx=5, pady=10, sticky="EW")# 页面提取的功能区,包括一个文件选择按钮,一个Entry输入框显示文件名称,一个Entry控件用以输入要提取的页码btn3 = tk.Button(window, text='选择提取页面文件', command=askfile3)btn3.grid(row=4, column=0)entry3 = tk.Entry(window, textvariable=filename3)entry3.grid(row=4, column=1, columnspan=3, ipadx=160)entry31 = tk.Entry(window)entry31.grid(row=4, column=5)entry31.insert(0, '页码范围')spilitBtn = tk.Button(window, text='提取页面', command=pdfspilit)spilitBtn.grid(row=5)# 定义一个分割线,用来分开两个功能,sticky指示线的方向sep = Separator(window, orient=HORIZONTAL)sep.grid(row=6, column=0, columnspan=8, padx=5, pady=10, sticky="EW")# 下面是PDF文件转Word文件的功能区,包括一个文件选择按钮,一个显示文件路径的Entry控件btn4 = tk.Button(window, text='转word的PDF文件', command=askfile4)btn4.grid(row=7, column=0)entry4 = tk.Entry(window, textvariable=filename4)entry4.grid(row=7, column=1, columnspan=3, ipadx=160)WordBtn = tk.Button(window, text='PDF转Word', command=pdftoword)   # 执行文件转换的控件,调用pdftoword程序WordBtn.grid(row=8)# 定义一个分割线,用来分开两个功能,sticky指示线的方向sep = Separator(window, orient=HORIZONTAL)sep.grid(row=9, column=0, columnspan=8, padx=5, pady=10, sticky="EW")# 下面是PDF文件转Excel文件的功能区,包括一个文件选择按钮,一个显示文件路径的Entry控件btn5 = tk.Button(window, text='转Excel的PDF文件', command=askfile5)btn5.grid(row=10, column=0)entry5 = tk.Entry(window, textvariable=filename5)entry5.grid(row=10, column=1, columnspan=3, ipadx=160)entry51 = tk.Entry(window)entry51.grid(row=10, column=5)entry51.insert(0, '起始页')entry52 = tk.Entry(window)entry52.grid(row=10, column=6)entry52.insert(0, '结束页')ExcelBtn = tk.Button(window, text='PDF转Excel', command=pdftoexcel)   # 执行文件转换的控件,调用pdftoword程序ExcelBtn.grid(row=11)# 定义一个分割线,用来分开两个功能,sticky指示线的方向sep = Separator(window, orient=HORIZONTAL)sep.grid(row=12, column=0, columnspan=8, padx=5, pady=10, sticky="EW")# 软件功能提示信息text = tk.Label(window, text='注意1:合并文件:选择两个pdf文件,并分别指定文件要合并的页码范围,合并后的文件默认在当前路径下的merger.pdf文件')text.grid(row=14, column=0, columnspan=8, sticky=tk.W)text2 = tk.Label(window, text="注意2:提取文件:提取一个pdf文件的指定页码,中间用英文','隔开,页码范围示例  1,2,3,5-9,11,15-19,提取后默认保存在当前路径下的split.pdf文件")text2.grid(row=15, column=0, columnspan=8, sticky=tk.W)text3 = tk.Label(window, text='注意3:PDF转word:仅支持可识别的文档转换,不支持图片识别功能,转换后文件为word.docx')text3.grid(row=16, column=0, columnspan=8, sticky=tk.W)text4 = tk.Label(window, text='注意4:PDF转Excel:分别输入表格所在PDF文件的起始页及结束页,在页码范围内,每一页都需要有表格否则会报错,转换后文件为excel.xlsx')text4.grid(row=17, column=0, columnspan=8, sticky=tk.W)# 主程序运行加载window.mainloop()

3. 代码打包

1. 打包过后程序运行出错

pyinstaller打包后,运行生成的exe报错“recursion is detected during loading of “cv2“ binary extensions.”
解决方法:

  1. 通过pip uninstall oepncv-python卸载,
  2. 通过pip install opencv-python --target 安装到程序路径。
  3. 通过pyinstaller -F -w --clean main.py --paths=“C:\Users\admin_zhouga\PycharmProjects\PDFinsert\venv\lib\site-packages\cv2” 进行打包

2. 打包命令

pyinstaller -F -w --clean --icon=“C:\Users\admin_zhouga\image\pdf.ico” C:\Users\admin_zhouga\PycharmProjects\PDFinsert\PDFcreate.py

–icon= 是给打包之后的文件exe文件添加一个图标

3.打包技巧

  1. 在创建工程的时候,需要在虚拟环境中创建。
  2. 在虚拟环境中安装pyinstaller
  3. 在虚拟环境的命令行中运行打包命令,如此可以缩小exe文件的大小。

相关内容

热门资讯

阿联酋最大银行及另两家中东银行... 观点网讯:5月8日,路透社报道指,阿联酋最大银行第一阿布扎比银行(First Abu Dhabi B...
深圳239亿地王易主,再造万象... 2017年,世茂集团豪掷239.43亿元拿下世茂深港国际中心地块,曾规划建筑高度达700米的深圳第一...
蔚来在安庆成立新能源科技公司 ... 天眼查App显示,近日,安庆蔚来新能源科技有限公司成立,法定代表人为姚蒀,注册资本500万人民币,经...
美国牛肉商期盼峰会重启对华出口 据路透社5月8日报道,美国牛肉生产商正期待特朗普与中国于5月14日至15日的峰会推动对华出口许可恢复...
创业板首家未盈利企业,市值突破... 5月8日,大普微总市值正式突破2000亿元大关。截至午间收盘,大普微涨14.07%,报493.1元/...
招商证券:董事长霍达因工作变动... 招商证券公告,公司董事长霍达因工作变动申请辞去董事长、执行董事等全部职务,辞任自辞呈送达董事会之日生...
原创 中... 【阅读须知】本文所引用的所有信息和数据,均为作者通过查阅官方资料与网络公开数据整理、分析而成,旨在为...
原创 从... 2026年5月5日,中国商务部发布了一项具有划时代意义的专项阻断禁令,这份公告让一向倚仗长臂管辖的美...
布米普特拉北京投资基金管理有限... 美国圣路易斯联邦储备银行总裁穆萨莱姆周三发出明确信号,美联储货币政策面临的潜在风险正在发生关键转向。...
加工的秘密:超精加工设备如何做... 你知道吗? 一根头发丝的直径大约0.07毫米,也就是70微米。 超精加工设备,可切出表面,其尺寸为0...
招商证券董事长霍达因工作变动离... 北京商报讯(记者 刘宇阳 实习生 王思奕)5月8日,招商证券发布关于公司董事长离任暨推举董事代行董事...
华帝股份营收创近3年新低,37... 乐居财经李兰近日,华帝股份(002035.SZ)发布2025年年度报告。 2025年,华帝股份实现营...
大模型融资杀疯了!月之暗面狂揽... 图源:视觉中国 5月7日,据华峰资本官微消息,国内头部大模型公司月之暗面(Kimi)于近日完成新一轮...
扎根长宁二十余载,仲利国际融资... 作为总部扎根上海长宁的优质台资金融企业,仲利国际融资租赁有限公司深耕融资租赁行业二十余载,始终坚守金...
估值210亿!李彦宏又将收获一... 来源:直通IPO,文/王非 国产GPU上市潮仍然汹涌,继两家登陆A股、两家登陆H股后,这家公司正推进...
基金“盲盒”拆了 公募基金正在迎来一场让投资者“看得懂”的变革。 近日,华夏、易方达、南方、招商等12家头部及特色基金...
原创 2... 前言 十年间,中国企业在印尼镍产业链累计砸下超过140亿美元,电厂、公路、码头和全套生产线,硬生生...
原创 欧... 俄罗斯卫星通讯社5月6日报道,欧盟宣布禁止欧洲银行为含有来自不可靠供应商的关键部件的可再生能源项目提...
原创 余... 2026年5月2日,在中国理财市场扎根十三年的余额宝,终于触碰到了一个让所有人错愕的数字——7日年化...
银华基金增聘谭普景共同管理银华... 来源:新浪基金∞工作室 5月8日,银华基金管理股份有限公司发布公告称,为银华中证机器人交易型开放式指...