python合并pdf文件并生成页面

1. 环境搭建

# python 版本 3.9.7
# 依赖包 reportlab==3.6.9,PyPdf2==1.27.3,pikepdf==3.0.8,pyinstaller==4.10

2.功能实现

2.1 建立合并文件的类 

import os
import sys
from PyPDF2 import PdfFileReader,PdfFileWriter
from reportlab.pdfgen import canvas
from reportlab.lib.units import cm
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
import pikepdf

class pdfmerge:

    def __init__(self):
        self.pdfspath='' # 存放pdf文件的文件夹路径
    #旋转页面
    def page_rotation(self,oldpdfpath, newpdfpath,msg):
        oldpdf = PdfFileReader(oldpdfpath)
        pagenums = oldpdf.getNumPages()
        newpdf = PdfFileWriter()
        for i in range(pagenums):
            page = oldpdf.getPage(i)
            size = page.mediaBox
            x, y = size.getUpperRight_x(),size.getUpperRight_y()
            # print(size)
            if x > y:
                # 顺时针旋转90度 90的倍数
                # page=page.rotateClockwise(90)
                msg.set('提示:正在旋转{}文件的第{}页'.format(oldpdfpath,i))
                page.rotateCounterClockwise(90)
            newpdf.addPage(page)
        with open(newpdfpath, 'wb') as f:
            newpdf.write(f)
        return f
    #合并文件
    def merge(self,pdfspath):#pdfspath 存放目标pdf的名称,路径,及命名序号
        pdf_hb = PdfFileWriter()
        for i in range(len(pdfspath)):
            obj = PdfFileReader(pdfspath[i][1])
            for j in range(obj.numPages):
                page = obj.getPage(j)
                pdf_hb.addPage(page)
        with open('合并的文件.pdf','wb') as f:
            pdf_hb.write(f)
        return f
    #解密pdf文件 用于处理不能编辑的pdf文件
    def pdf_Crack(self,startFile):
        endFile=startFile[:-4]+' '+'.pdf'
        with pikepdf.open(startFile) as pdf:
            pdf.save(endFile)
        os.remove(startFile)
        return endFile
    # 插入页码  生成合并后文件的pdf水印,使用reportlab实现
    def create_mark(self,pages):
        file_name = 'yam.pdf'
        c = canvas.Canvas(file_name)
        pdfmetrics.registerFont(TTFont('yahei', resource_path('song.ttc')))

        for i in range(1, pages + 1):
            c.setFont('yahei', 14)
            c.drawString(9.5 * cm, 1 * cm, '第{}页'.format(i))
            c.showPage()
        c.save()
        return file_name
    # 为合并后的文件每页添加水印,以实现编写页码
    def add_watermark1(self,pdf_file_in, pdf_file_out):
        pdf_output = PdfFileWriter()
        input_stream = open(pdf_file_in, 'rb')
        pdf_input = PdfFileReader(input_stream, strict=False)

        # 获取PDF文件的页数
        pageNum = pdf_input.getNumPages()
        pdf_file_mark = self.create_mark(pageNum)
        # 读入水印pdf文件
        pdf_watermark = PdfFileReader(open(pdf_file_mark, 'rb'), strict=False)
        # 给每一页打水印
        for i in range(pageNum):
            page = pdf_input.getPage(i)
            page.mergePage(pdf_watermark.getPage(i))
            page.compressContentStreams()  # 压缩内容
            pdf_output.addPage(page)
        pdf_output.write(open(pdf_file_out, 'wb'))
    # 获取目标文件夹下的所有pdf,返回列表,元素也为列表([pdf名称,pdf路径,序号+名称])
    def getpdffiles(self):
        pdfs=[]
        calalog=[]
        for root,dirs,files in os.walk(self.pdfspath):
            calalog.append(dirs)
            for f in files:
                if f.endswith(('.pdf','.PDF')):
                    pdfs.append([f.split('.')[1],os.path.join(root,f),f])
        return sorted(pdfs,key=lambda x:(x[2][:3])),calalog[0]
    #生成pdf文件的目标,返回txt文本
    def create_calalog(self,pdfnames):
        with open('目录文件.txt', 'w') as f:
            zys = 1
            for i in range(len(pdfnames)):
                pages = PdfFileReader(pdfnames[i][1]).getNumPages()
                aa = pdfnames[i][2] + '.......' + str(zys)
                f.writelines(aa)
                f.write('\n')
                zys = zys + pages
        f.close()

2.2 界面

import tkinter as tk
import tkinter.filedialog
from pdfutils import pdfmerge
from PyPDF2 import PdfFileReader
import time
import threading
root = tk.Tk()
root.title('文件汇编小程序v2022-04')
root.geometry('600x200+{}+{}'.format(int((root.winfo_screenwidth()-600)/2),
              int((root.winfo_screenheight()-200)/2)))
tk.Label(root,text='请选择文件夹:',font=('simhei',14)).place(x=5,y=15)
pEty=tk.Entry(root)
pEty.place(x=150,y=15,width=300)
cBt=tk.Button(root,text='选  择',font=('simhei',14))
cBt.place(x=480,y=10)
tk.Button(root,text='退  出',font=('simhei',14),command=root.quit).place(x=320,y=150)
rBt=tk.Button(root,text='运  行',font=('simhei',14))
rBt.place(x=180,y=150)
def cBtf():
    path=tkinter.filedialog.askdirectory()
    pEty.delete('0','end')
    pEty.insert('0',path)
cBt['command']=cBtf
#提示语句
msg=tk.StringVar()
tk.Label(root,textvariable=msg,font=('simhei',14),fg='red').place(x=10,y=60)
msg.set('提示:')
def runing():
    start=time.time()
    app=pdfmerge()
    path=pEty.get()
    try:
        app.pdfspath=path
        msg.set('提示:正在对加密文件进行解密...')
        pdfpaths = app.getpdffiles()[0]
        for pdfpath in pdfpaths:
            if PdfFileReader(pdfpath[1]).isEncrypted:
                msg.set('提示:正在解密{}'.format(pdfpath[0]))
                app.pdf_Crack(pdfpath[1])
        msg.set('提示:已完成目标文件夹下所有加密文件的解密!')
        time.sleep(1)
        pdfpaths = app.getpdffiles()[0]
        msg.set('提示:正在导出目标...')
        app.create_calalog(pdfpaths)
        msg.set('提示:目标导出完成!')
        time.sleep(1)
        msg.set('提示:正在合并文件...')
        app.merge(pdfpaths)
        msg.set('提示:合并文件完成!')
        time.sleep(1)
        msg.set('提示:正在调整页面方向...')
        app.page_rotation('合并的文件.pdf', '合并的文件(旋转页面).pdf',msg)
        msg.set('提示:页面方向调整完成!')
        time.sleep(1)
        msg.set('提示:正在生成页码...')
        app.add_watermark1('合并的文件(旋转页面).pdf', '合并的文件(已编写页面).pdf')
        endt=time.time()
        msg.set('提示:文件汇编完成!总耗时:{}秒'.format(int(start-endt)))
    except:
        msg.set('提示:请选择正确的文件夹')
def run2():
    threading.Thread(target=runing).start()
rBt['command']=run2
root.mainloop()

预览:

3. 打包 

3.1 创建虚拟环境

python -m venv d:\venv

pip install 依赖库

3.2 添加静态文件

#定义函数,并将类中注册字体的相对路径使用此函数
def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base_path, relative_path)

3.3 生成并修改spec文件

pyi-makespec D:\202112study\pdf\app\ui.py

#修改spec
# -*- mode: python ; coding: utf-8 -*-


block_cipher = None


a = Analysis(['D:\\202112study\\pdf\\app\\ui.py'],
             pathex=[],
             binaries=[],
             datas=[],#修改此处,改为datas=[('song.ttc','.')]
             hiddenimports=[],
             hookspath=[],
             hooksconfig={},
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)

exe = EXE(pyz,
          a.scripts, 
          [],
          exclude_binaries=True,
          name='ui',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          console=False,
          disable_windowed_traceback=False,
          target_arch=None,
          codesign_identity=None,
          entitlements_file=None )
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas, 
               strip=False,
               upx=True,
               upx_exclude=[],
               name='ui')

3.4 生成exe

pyinstaller -F D:\202112study\pdf\app\ui.spec

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值