Python练手项目:PDF小工具-fitz版

Python练手项目:PDF小工具-fitz版
python对办公一族来说,是个提高办公效率的得力利器。熟练使用它,可以轻松完成很多繁杂的事情。它可以轻松地操作Word、Excel、PDF这种文档。
今天需要整理一份资料,需要把多个pdf合并为一个,wps这些软件自然是有这个功能,但一般都是收费的,百度上也有很多网站,但资料上传到别人的网站,始终觉得还是不太可靠,故自己搜索了一下使用python来处理pdf文件,故此用tk制作了PDF小工具。
安装以下库:
python -m pip install -U pip
pip install PyMuPDF==1.19.0 -i https://pypi.mirrors.ustc.edu.cn/simple/
pdf_tool_fitz.py
源码如下:

#pip install PyMuPDF==1.19.0 -i https://pypi.mirrors.ustc.edu.cn/simple/
from pathlib import Path
import subprocess
import time
import sys
import tkinter as tk
from tkinter import ttk
import tkinter.filedialog as fd
import tkinter.messagebox as mb
import base64
import fitz
import threading

class PdfHandler:
    page_count=None
    page_index=None
    img_path=None
    def pdf_to_imgs(self,pdf_path,img_path,zoom_x,zoom_y,rotation_angle):
        '''
        pdf文件每页内容都转换成图片
        :param pdf_path:pdf文件的路径
        :param img_path:图像要保存的路径
        :param zoom_x:x方向的缩放系数
        :param zoom_y:y方向的缩放系数
            zoom_x和zoom_y一般取相同值,值越大,图像分辨率越高
        :param rotation_angle:旋转角度
        :return:
        '''
        # 如果没有存储文件的目录,则创建
        if not Path(img_path).exists():
            Path(img_path).mkdir()
            
        # 打开PDF文件
        with fitz.open(pdf_path) as pdf:
            self.page_count=pdf.page_count
            # 逐页读取PDF
            for page_index in range(0, pdf.pageCount):
                self.page_index=page_index
                page = pdf[page_index]
                # 设置缩放和旋转系数,zoom_x, zoom_y取相同值,表示等比例缩放
                trans = fitz.Matrix(zoom_x, zoom_y).prerotate(rotation_angle)
                pm = page.getPixmap(matrix=trans, alpha=False)
                self.img_path=f'{img_path}/{page_index}.png'
                self.img_path=self.img_path.replace('/',"\\")
                # 开始写图像
                pm.writePNG(self.img_path) # 第1张图片名:0.png,以此类推
                pm=None

    def imgs_to_pdf(self,img_path, new_pdf_name):
        '''
        将图片转为pdf
        :param imgPath: 图片路径
        :param new_pdf_name: 多张图片合并成的pdf文件名
        :return:
        '''
        with fitz.open() as doc:  # 新建一个空文档
            img_list=[]
            for item in Path(img_path).iterdir():
                img_list.append(item.name)
            for page_index in range(len(img_list)):
                self.page_index=self.page_index+1
                img = fitz.open(f'{img_path}/{page_index}.png')  # 打开图片
                pdfbytes = img.convertToPDF()  # 使用图片创建单页的 PDF
                with fitz.open("pdf", pdfbytes) as imgpdf:
                    doc.insert_pdf(imgpdf)
                img.close()
            doc.save(new_pdf_name)
    
    def imgs_2_pdf(self,old_pdf_names, new_pdf_name):
        '''
        将图片转为pdf
        :param imgPath: 图片路径
        :param new_pdf_name: 多张图片合并成的pdf文件名
        :return:
        '''
        with fitz.open() as doc:  # 新建一个空文档
            for old_pdf_name in old_pdf_names:
                img = fitz.open(old_pdf_name)  # 打开图片
                pdfbytes = img.convertToPDF()  # 使用图片创建单页的 PDF
                with fitz.open("pdf", pdfbytes) as imgpdf:
                    doc.insert_pdf(imgpdf)
                img.close()
            doc.save(new_pdf_name)
    
    def img_invert_img(self,old_img_name, new_img_name):
        '''
        将图片转为pdf
        :param imgPath: 图片路径
        :param new_pdf_name: 多张图片合并成的pdf文件名
        :return:
        '''
        with fitz.open() as doc:  # 新建一个空文档
            img = fitz.open(old_img_name)  # 打开图片
            pdfbytes = img.convertToPDF()  # 使用图片创建单页的 PDF
            with fitz.open("pdf", pdfbytes) as imgpdf:
                doc.insert_pdf(imgpdf)
            img.close()
            img = doc.get_page_images(0)[0]
            xref = img[0] #图片的xref编号,
            base = img[1] #图片的基本名字,比如 'img0'
            pix = fitz.Pixmap(doc, xref)
            if pix.n < 5:  # 这是一个灰度或者RGB图片
                pix.invertIRect()
                pix.writePNG(new_img_name)
            else:  # 这是一个CMYK图片
                pix1 = fitz.Pixmap(fitz.csRGB, pix)
                pix1.invertIRect()
                pix1.writePNG(new_img_name)
                pix1 = None
            pix = None
            '''
            pm=doc[0].getPixmap(dpi=600,alpha=False)
            pm.invertIRect()
            pm.writePNG(new_img_name)
            pm=None
            '''
    
    def merge_pdfs(self,old_pdf_names,new_pdf_name):
        '''
        从pdf文件合成为新的pdf文件
        :param old_pdf_names: pdf文件名数组
        :param new_pdf_name: 合并出的新pdf文件名
        :return:
        '''
        print(old_pdf_names)
        print(new_pdf_name)
        file_writer = fitz.open()
        for pdf in old_pdf_names:
            file_reader = fitz.open(pdf)# 循环读取需要合并pdf文件
            file_writer.insert_pdf(file_reader)
            file_reader.close()
        file_writer.save(new_pdf_name)
        file_writer.close()
   
    def split_pdf(self,old_pdf_name, new_pdf_name, from_page, to_page):
        '''
        从pdf文件中拆分出部分,拆出部分成为新的pdf文件
        :param old_pdf_name: 原pdf文件名
        :param new_pdf_name: 拆分后合并出的新pdf文件名
        :param from_page: 原pdf文件起始页码索引(0开始,默认0)
        :param to_page: 原pdf文件结尾页码索引(0开始,默认最后一页)
        :return:
        '''
        with fitz.open(old_pdf_name) as old_pdf, fitz.open() as new_pdf:
            print(f"从:{from_page}")
            to_page-=1
            print(f"到:{to_page}")
            new_pdf.insert_pdf(old_pdf,from_page,to_page)
            new_pdf.save(new_pdf_name)
            
    def get_pdf_text(self,pdf_path):
        '''
        获取每页pdf文件文本
        :param pdf_path: pdf文件路径
        :return:
        '''
        # 打开pdf文件,并新建html文件
        with fitz.open(pdf_path) as pdf:

            # 遍历每一页pdf,并显示进度条
            for page in pdf:
                text = page.get_text() #提取文本,传入参数'html'即:page.get_text('html') 则提取每页内容为html
            print(f'第{page+1}页解析内容:\n{text}')
    
    def get_pdf_images(self,img_path,pdf_path):
        '''
        获取每页pdf文件所有图片
        :param pdf_path: pdf文件路径
        :return:
        '''
        # 如果没有存储文件的目录,则创建
        if not Path(img_path).exists():
            Path(img_path).mkdir()
        doc = fitz.open(pdf_path)
        self.page_count=doc.page_count
        page_index=0
        for i in range(len(doc)):
            self.page_index=i
            for img in doc.get_page_images(i):
                xref = img[0] #图片的xref编号,
                #base = img[1] #图片的基本名字,比如 'img0'
                pix = fitz.Pixmap(doc, xref)
                self.img_path=f"{img_path}/{page_index}.png"
                if pix.n < 5:  # 这是一个灰度或者RGB图片
                    pix.writePNG(self.img_path)
                else:  # 这是一个CMYK图片
                    pix1 = fitz.Pixmap(fitz.csRGB, pix)
                    pix1.writePNG(self.img_path)
                    pix1 = None
                pix = None  # 让图片像素图清除内存
                page_index+=1
        doc.close()

# 防止字符串乱码
# os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.UTF8'
data=[]
id=0
mydir='D:/'
kind='PDF'
PdfHandler=PdfHandler()

def thread_it(func,args):
	'''将函数打包进线程'''
	# 创建
	t = threading.Thread(target=func, args=args)
	# 守护 !!!
	t.setDaemon(True)
	# 启动
	t.start()
	# 阻塞--卡死界面!
	# t.join()

def base64_to_image(base64_string, image_path):
    base64_data = base64_string.encode("utf-8")
    image_data = base64.b64decode(base64_data)
    with open(image_path, "wb") as image_file:
        image_file.write(image_data)

base64_string = '''
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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值