使用PyMuPDF库的PDF合并和分拆程序

PDF工具应用程序是一个使用wxPython和PyMuPDF库编写的简单工具,用于合并和分拆PDF文件。它提供了一个用户友好的图形界面,允许用户选择源文件夹和目标文件夹,并对PDF文件进行操作。
C:\pythoncode\blog\pdfmergandsplit.py
在这里插入图片描述

功能特点

  • 选择文件夹:用户可以通过应用程序界面轻松选择源文件夹和目标文件夹。
  • 合并PDF文件:应用程序允许用户选择要合并的PDF文件,并将它们合并成一个单独的PDF文件。
  • 分拆PDF文件:用户可以选择一个PDF文件,将其分拆成多个单独的PDF文件,每个文件包含一个页面。

程序实现

该应用程序使用了以下库和模块:

  • wxPython:用于创建应用程序的图形用户界面。
  • PyMuPDF:用于处理PDF文件的库。

应用程序的主要部分是一个继承自wxPython的wx.Frame类的主窗口。窗口包含以下组件:

  • 选择源文件夹和目标文件夹的按钮。
  • PDF文件列表框,显示源文件夹中的PDF文件。
  • 合并和分拆按钮,用于执行相应的操作。

当用户点击选择源文件夹按钮时,应用程序显示一个文件夹选择对话框,用户可以选择源文件夹。选择后,应用程序获取文件夹路径,并列出文件夹中的PDF文件。然后,合并和分拆按钮变为可用状态,用户可以执行相应的操作。

合并按钮的点击事件会弹出一个文本输入对话框,要求用户输入合并后的文件名。用户输入后,应用程序调用PyMuPDF库合并选定的PDF文件,并将合并后的PDF文件保存到目标文件夹中。

分拆按钮的点击事件会遍历选定的PDF文件,并使用PyMuPDF库将每个页面保存为单独的PDF文件。

代码示例

以下是应用程序的代码示例:

import os
import wx
import fitzclass PDFToolApp(wx.Frame):def __init__(self, parent, title):super(PDFToolApp, self).__init__(parent, title=title, size=(400, 400))self.panel = wx.Panel(self)self.source_folder_btn = wx.Button(self.panel, -1, "选择源文件夹")self.target_folder_btn = wx.Button(self.panel, -1, "选择目标文件夹")self.pdf_list = wx.CheckListBox(self.panel, -1, choices=[], style=wx.LB_MULTIPLE)self.merge_btn = wx.Button(self.panel, -1, "合并")self.split_btn = wx.Button(self.panel, -1, "分拆")self.merge_btn.Disable()self.split_btn.Disable()self.source_folder_btn.Bind(wx.EVT_BUTTON, self.on_select_source_folder)self.target_folder_btn.Bind(wx.EVT_BUTTON, self.on_select_target_folder)self.merge_btn.Bind(wx.EVT_BUTTON, self.on_merge)self.split_btn.Bind(wx.EVT_BUTTON, self.on_split)sizer = wx.BoxSizer(wx.VERTICAL)sizer.Add(self.source_folder_btn, 0, wx.ALIGN_CENTER | wx.ALL, 10)sizer.Add(self.target_folder_btn, 0, wx.ALIGN_CENTER | wx.ALL, 10)sizer.Add(self.pdf_list, 1, wx.EXPAND | wx.ALL, 10)sizer.Add(self.merge_btn, 0, wx.ALIGN_CENTER | wx.ALL, 10)sizer.Add(self.split_btn, 0, wx.ALIGN_CENTER | wx.ALL, 10)self.panel.SetSizer(sizer)self.Show()def on_select_source_folder(self, event):dlg = wx.DirDialog(self, "选择源文件夹", style=wx.DD_DEFAULT_STYLE)if dlg.ShowModal() == wx.ID_OK:source_folder_path = dlg.GetPath()self.pdf_list.Set(self.get_pdf_files(source_folder_path))self.merge_btn.Enable()self.split_btn.Enable()dlg.Destroy()def on_select_target_folder(self, event):dlg = wx.DirDialog(self, "选择目标文件夹", style=wx.DD_DEFAULT_STYLE)if dlg.ShowModal() == wx.ID_OK:self.target_folder_path = dlg.GetPath()dlg.Destroy()def on_merge(self, event):selected_items = self.pdf_list.GetCheckedItems()if len(selected_items) > 0:dlg = wx.TextEntryDialog(self, "请输入合并后的文件名(不带扩展名):", "合并文件")if dlg.ShowModal() == wx.ID_OK:output_filename = dlg.GetValue()output_filepath = os.path.join(self.target_folder_path, output_filename + ".pdf")self.merge_pdfs(selected_items, output_filepath)wx.MessageBox("PDF文件合并完成!", "完成", wx.OK | wx.ICON_INFORMATION)dlg.Destroy()def on_split(self, event):selected_items = self.pdf_list.GetCheckedItems()if len(selected_items) > 0:for index in selected_items:pdf_filename = self.pdf_list.GetString(index)pdf_filepath = os.path.join(self.target_folder_path, pdf_filename)self.split_pdf(pdf_filename, pdf_filepath)wx.MessageBox("PDF文件分拆完成!", "完成", wx.OK | wx.ICON_INFORMATION)def merge_pdfs(self, selected_items, output_filepath):pdf_merger = fitz.open()for index in selected_items:pdf_filename = self.pdf_list.GetString(index)pdf_filepath = os.path.join(self.target_folder_path, pdf_filename)pdf = fitz.open(pdf_filepath)pdf_merger.insert_pdf(pdf)pdf_merger.save(output_filepath)pdf_merger.close()def split_pdf(self, pdf_filename, pdf_filepath):pdf = fitz.open(pdf_filepath)num_pages = pdf.page_countfor i in range(num_pages):output_filename = f"{pdf_filename[:-4]}_{i+1}.pdf"output_filepath = os.path.join(self.target_folder_path, os.path.basename(output_filename) )print("output_filename:"+output_filename)page = pdf[i]new_pdf = fitz.open()new_pdf.insert_pdf(pdf, from_page=i, to_page=i)new_pdf.save(output_filepath)print("self.target_folder_path:"+self.target_folder_path)print("output_filepath:"+output_filepath)new_pdf.close()pdf.close()def get_pdf_files(self, folder_path):pdf_files = []for filename in os.listdir(folder_path):if filename.endswith(".pdf"):pdf_files.append(folder_path+'/'+filename)return pdf_filesif __name__ == "__main__":app = wx.App()PDFToolApp(None, "PDF工具")app.MainLoop()

总结

PDF工具应用程序是一个使用wxPython和PyMuPDF库编写的简单实用工具,可用于合并和分拆PDF文件。它提供了一个直观的图形界面,使用户能够轻松选择文件夹和执行操作。无论是处理大量PDF文件还是简单的分拆操作,该应用程序都能满足用户的需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/94496.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

音视频实时通话解决方案

1、问题提出 想要实现音视频通话,对于大部分人可能会觉得很难,但是实际上,有些事情并没有大家想的那样困难,只要功夫深,铁杵磨成针。 机缘巧合下,在业务中,我也遇到了一个业务场景需要实现音视频通话,我们不可能自己从零开始干,我本次用到的核心是WebRTC。 2、WebRT…

同伦问题与同伦算法

同伦问题 据我所知,这篇博客是CSDN上少数几篇讲同伦算法的博客之一考虑同伦算法的目的 扩大初值选取范围解决非线性代数方程组的全部解计算问题 同伦算法中的基本概念 考虑求的解人为地引入参数t,构造一个函数族使得 同时假设的解已知,从出发可以求解对…

在项目中如何解除idea和Git的绑定

在项目中如何解除idea和Git的绑定 1、点击File--->Settings...(CtrlAltS)--->Version Control--->Directory Mappings--->点击取消Git的注册根路径: 2、回到idea界面就没有Git了: 3、给这个项目初始化 这样就可以重新绑定远程仓库了&#x…

部署piwigo网页 通过cpolar分享本地电脑上的图片

通过cpolar分享本地电脑上有趣的照片:发布piwigo网页 文章目录 通过cpolar分享本地电脑上有趣的照片:发布piwigo网页前言1. 设定一条内网穿透数据隧道2. 与piwigo网站绑定3. 在创建隧道界面填写关键信息4. 隧道创建完成 总结 前言 首先在本地电脑上部署…

13、Redis与Mysql数据双写一致性

Redis与Mysql数据双写一致性 1、 复习+面试题 先动Mysql,再动Redis,两害相衡取其轻,避免Redis业务key突然消失,多线程请求集火打满mysql 动,写操作,先更新数据库,在删除缓存。回写的…

实验篇——亚细胞定位

实验篇——亚细胞定位 文章目录 前言一、亚细胞定位的在线网站1. UniProt2. WoLFPSORT3. BUSCA4. TargetP-2.0 二、代码实现1. 基于UniProt(不会)2. 基于WoLFPSORT后续(已完善,有关代码放置于[python爬虫学习(一&#…

【大数据Hive】hive 事务表使用详解

目录 一、前言 二、Hive事务背景知识 hive事务实现原理 hive事务原理之 —— delta文件夹命名格式 _orc_acid_version 说明 bucket_00000 合并器(Compactor) 二、Hive事务使用限制 参数设置 客户端参数设置 客户端参数设置 三、Hive事务使用操作演示 操作步骤 客…

Windows系统Git安装教程(详细Git安装过程)

获取Git安装程序 到Git官网下载,网站地址:https://git-scm.com/downloads,如下图: 因为我们是用Windows系统上的浏览器访问的,Git官网自动之别到了我使用的操作系统,所以右侧直接显示下载使用Windows系统的…

gromacs教程练习1

gromacs能在win上运行,还是个开源的软件,这都很值得入手学习 记录下gromacs教程的练习情况: Lysozyme in water 水中的溶菌酶,嗯,估计就是把蛋白处理后放在显试溶剂里跑MD这个模拟。 1、文件的准备: 1、…

【仿写tomcat】四、解析http请求信息,响应给前端,HttpServletRequest、HttpServletResponse的简单实现

思考 在解析请求之前我们要思考一个问题,我们解析的是其中的哪些内容? 对于最基本的实现,当然是请求类型,请求的url以及请求参数,我们可以根据请求的类型作出对应的处理,通过url在我们的mapstore中找到se…

【数据结构OJ题】合并两个有序链表

原题链接:https://leetcode.cn/problems/merge-two-sorted-lists/description/ 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 可以先创建一个空链表,然后依次从两个有序链表中选取最小的进行尾插操作。(有点类似双…

基于docker搭建pytest自动化测试环境(docker+pytest+jenkins+allure)

pytest搭建自动化测试环境(dockerpytestjenkinsallure) 这里我以ubuntu18为例 如果有docker环境,可以直接拉取我打包好的镜像docker pull ziyigun/jenkins:v1.0 1 搭建Docker 1.1 安装docker # 配置docker安装环境 sudo apt-get install ap…

Android Studio实现解析HTML获取图片URL将图片保存到本地

目录 效果activity_main.xmlMainActivityImageItemImageAdapter 效果 项目本来是要做成图片保存到手机然后读取数据后瀑布流展示&#xff0c;但是有问题&#xff0c;目前只能做到保存到手机 activity_main.xml <?xml version"1.0" encoding"utf-8"?…

C++写文件,直接写入结构体

C写文件&#xff0c;直接写入结构体 以前写文件都是写入字符串或者二进制再或者就是一些配置文件&#xff0c;今天介绍一下直接写入结构体&#xff0c;可以在软件参数较多的时候直接进行读写&#xff0c;直接将整个结构体写入和读取&#xff0c;看代码&#xff1a; #include&…

文本图片怎么转Excel?分享一些好用的方法

在处理数据时&#xff0c;Excel 是一个非常强大的工具&#xff0c;但有时候需要将文本和图片转换为 Excel 格式&#xff0c;这可能会让人感到困惑。在本文中&#xff0c;我们将介绍一些好用的方法&#xff0c;以便您能够轻松地将文本和图片转换成 Excel 格式。 将文本图片为Exc…

vue3 videojs实现播放器,动态更改src

一、背景 vue3下载第三方插件videojs&#xff0c;达到播放器的效果&#xff0c;并且点击事件能够动态更改播放器的src。实现思路&#xff1a; 场景一&#xff1a;只有一个播放器&#xff0c;当点击事件&#xff0c;直接赋值&#xff0c;动态更改封装好的组件的src参数&#xff…

线程|线程的使用、四种实现方式

1.线程的实现方式 1.用户级线程 开销小&#xff0c;用户空间就可以创建多个。缺点是&#xff1a;内核无法感知用户级多个线程的存在&#xff0c;把其当作只有一个线程&#xff0c;所以只会提供一个处理器。 2.内核级线程 相对于用户级开销稍微大一点&#xff0c;可以利用多…

无涯教程-Perl - setgrent函数

描述 此功能将枚举设置(或重置)到组条目集的开头。该函数应在第一次调用getgrent之前调用。 语法 以下是此函数的简单语法- setgrent返回值 此函数不返回任何值。 例 以下是显示其基本用法的示例代码- #!/usr/bin/perl -wwhile( ($name,$passwd,$gid,$members)getgrent…

c语言每日一练(9)

前言&#xff1a;每日一练系列&#xff0c;每一期都包含5道选择题&#xff0c;2道编程题&#xff0c;博主会尽可能详细地进行讲解&#xff0c;令初学者也能听的清晰。每日一练系列会持续更新&#xff0c;暑假时三天之内必有一更&#xff0c;到了开学之后&#xff0c;将看学业情…

QT的设计器介绍

设计器介绍 Qt制作 UI 界面&#xff0c;一般可以通过UI制作工具QtDesigner和纯代码编写两种方式来实现。纯代码实现暂时在这里不阐述了在后续布局章节详细说明&#xff0c;QtDesigner已经继承到开发环境中&#xff0c;在工程中直接双击ui文件就可以直接在QtDesigner设计器中打…