python程序:pdf文件分割工具

支持两种分割方式

1.可将pdf文件按固定页数分割,例如:100页的PDF文件,按固定页数30进行分割,则实际分割为1-30,31-60,61-90,91-100


微信图片_20210418221623.png

2.可将pdf文件按指定页码分割,例如:100页的PDF文件,按指定页码20,50,100进行分割,则实际分割为1-20,21-50,51-100


微信图片_20210418221803.png

分割成功后,输出到源文件同目录下的新目录中(新目录与源文件名相同)

3.完整代码如下:

from PyPDF2 import PdfFileReader, PdfFileWriter
import PySimpleGUI as sg
import os
import math
import re
import pyperclip

global_option = 1

# 按指定固定页数分割PDF
def pdfSplitOp1(input_path_file, output_path, file_size):
    try:
        fine_name = os.path.splitext(os.path.basename(input_path_file))[0]
        pdf = PdfFileReader(input_path_file, False)
        idx = 0
        for page in range(pdf.getNumPages()):
            # 初始化
            if((page % file_size) == 0):
                idx = idx + 1
                pdf_writer = PdfFileWriter()
                output_path_file = os.path.join(output_path, '{}-{}.pdf'.format(fine_name, idx))
            pdf_writer.addPage(pdf.getPage(page))
            with open(output_path_file, 'wb') as out:
                pdf_writer.write(out)
        return 'success'
    except Exception as e:
        return repr(e)

# 按指定页码分割PDF
def pdfSplitOp2(input_path_file, output_path, list_number):
    try:
        fine_name = os.path.splitext(os.path.basename(input_path_file))[0]
        pdf = PdfFileReader(input_path_file, False)
        idx = 0
        start_page = 0
        for num in list_number:
            idx = idx + 1
            end_page = int(num)
            pdf_writer = PdfFileWriter()
            output_path_file = os.path.join(output_path, '{}-{}.pdf'.format(fine_name, idx))
            for page in range(start_page, end_page):
                pdf_writer.addPage(pdf.getPage(page))
            with open(output_path_file, 'wb') as out:
                pdf_writer.write(out)
            start_page = int(num)
        return 'success'
    except Exception as e:
        return repr(e)

# 提示对话框,用户知悉即可
def infoDialog(info):
    sg.popup('', info, '',
             title='提示',
             custom_text='  知道了  ',
             background_color='gray',
             text_color='black',
             button_color='#9FB8AD')

# 继续执行对话框,用户点击下一步可继续执行
def nextDialog(info):
    return sg.popup('', info, '',
                    title='询问',
                    custom_text=('  分割  ', '  取消  '),
                    background_color='gray',
                    text_color='black',
                    button_color='#9FB8AD')

def openFolderDialog(info):
    return sg.popup('', info, '',
                    title='询问',
                    custom_text=('  打开  ', '  不用  '),
                    background_color='green',
                    text_color='black',
                    button_color='#9FB8AD')

# 错误对话框,用户知悉异常详细信息
def exceptionDialog(info):
    return sg.popup('', info, '',
             title='异常',
             custom_text=('  知道了  ', '  复制异常信息  '),
             background_color='red',
             text_color='black',
             button_color='#9FB8AD')

# 检查固定页数填写值是否符合格式要求
def checkFileSize(fileSize):
    if re.match(r"^\+?[1-9][0-9]*$", fileSize) is None:
        return False
    else:
        return True

# 检查指定页码填写值是否符合格式要求
def checkSizeList(sizeList):
    print(sizeList)
    if re.match(r"^([0-9]+)(,([0-9]+))*$", sizeList) is None:
        return False
    else:
        return True

# 设置应用程序的主题
sg.theme('DarkAmber')

layout = [
    [sg.Text('1. 请选择PDF文件')],
    [sg.FileBrowse('选择...', size=(10, 1), file_types=(('PDF Files', '*.pdf'),)),
     sg.Input(size=(100, 1), key='_INPUT_PATH_FILE_')],
    [sg.Text('_'*30)],
    [sg.Text('2. 请选择分割方式')],
    [sg.Radio('固定页数', 'S1', enable_events=True, key='_OP01_', default=True),
     sg.Radio('指定页码', 'S1', enable_events=True, key='_OP02_')],
    [sg.Text('按固定页数', key='_INFO1_'),
     sg.Input('', size=(16, 1), key='_INFO2_'),
     sg.Text('进行分割(例如:100页的PDF文件,按固定页数30进行分割,则实际分割为1-30,31-60,61-90,91-100)', size=(80, 1), key='_INFO3_')],
    [sg.Button('分割PDF文件', size=(16,1), key='_SPLIT_PDF_'),
     sg.Button('退出', size=(16,1), key='_CANCEL_')]
]

window = sg.Window('PDF分割工具', layout)

while True:
    event, values = window.read()
    if event == '_OP01_':
        # 选择了按固定页数分割
        global_option = 1
        window['_INFO1_'].update('按固定页数')
        window['_INFO2_'].update('')
        window['_INFO3_'].update('进行分割(例如:100页的PDF文件,按固定页数30进行分割,则实际分割为1-30,31-60,61-90,91-100)')
    elif event == '_OP02_':
        # 选择了按指定页码分割
        global_option = 2
        window['_INFO1_'].update('按指定页码')
        window['_INFO2_'].update('')
        window['_INFO3_'].update('进行分割(例如:100页的PDF文件,按指定页码20,50,100进行分割,则实际分割为1-20,21-50,51-100)')
    elif event == '_SPLIT_PDF_':
        # 点击了分割PDF按钮
        # 校验输入信息
        inputPathFile = values['_INPUT_PATH_FILE_']
        try:
            pageCount = PdfFileReader(inputPathFile, False).getNumPages()
        except FileNotFoundError:
            # 源文件不存在
            info = '源文件不存在,请选择需要分割的PDF文件。'
            infoDialog(info)
            continue
        if(1 == global_option):
            # 如果选择了按指定页码分割
            fileSize = values['_INFO2_']
            # 检查参数
            if checkFileSize(fileSize):
                # 如果参数格式正确
                iFileSize = int(values['_INFO2_'])
                if(iFileSize >= pageCount):
                    # 如果参数值不正确
                    info = '设置的固定页数(%s)不能大于或等于源文件的总页数(%s)' % (iFileSize, pageCount)
                    infoDialog(info)
                    continue
                else:
                    # 如果参数值正确,提示是否执行分割
                    fileCount = math.ceil(pageCount / iFileSize)
                    info = '源文件总计%s页,每份文件%s页,可以分割成%s份文件。\r\n\r\n是否分割PDF文件?' % (pageCount, iFileSize, fileCount)
                    rtn = nextDialog(info)
                    if(rtn is not None and '分割' == rtn.strip()):
                        # 点击了分割按钮
                        # 执行分割文件
                        inputPathFile = values['_INPUT_PATH_FILE_']
                        inputPath = os.path.abspath(os.path.dirname(inputPathFile) + os.path.sep + ".")
                        inputFile = os.path.splitext(os.path.basename(inputPathFile))[0].split('.')[0]
                        outputPath = '{}\\{}'.format(inputPath, inputFile)
                        # 创建输出文件夹,先判断是否存在,存在则不创建,不存在则新建,使用源文件名称作为文件夹名称
                        try:
                            if(not os.path.exists(outputPath)):
                                os.mkdir(outputPath)
                        except OSError:
                            # 创建输出文件夹失败
                            rtn = exceptionDialog('创建输出文件夹失败!\r\n\r\n异常信息:%s' % OSError)
                            if (rtn is not None and '复制异常信息' == rtn.strip()):
                                pyperclip.copy(exceptionInfo)
                                continue
                            else:
                                continue
                        rtn = pdfSplitOp1(inputPathFile, outputPath, iFileSize)
                        if('success' == rtn):
                            rtn = openFolderDialog('分割成功!\r\n\r\n是否打开文件夹?\t\t\t\t\t')
                            if(rtn is not None and '打开' == rtn.strip()):
                                os.system("explorer.exe %s" % outputPath)
                            else:
                                continue
                        else:
                            exceptionInfo = rtn
                            rtn = exceptionDialog('执行失败!\r\n\r\n异常信息:%s' % exceptionInfo)
                            if (rtn is not None and '复制异常信息' == rtn.strip()):
                                pyperclip.copy(exceptionInfo)
                                continue
                            else:
                                continue
                        continue
                    elif(rtn is not None and '取消' == rtn.strip()):
                        # 点击了取消按钮
                        continue
                    else:
                        # 点击了标题栏的关闭(X)
                        continue
            else:
                # 如果参数格式不正确
                info = '请输入正确的固定页数(大于等于1的整数)。'
                infoDialog(info)
                continue
        elif(2 == global_option):
            # 如果选择了按指定页码分割
            sizeList = values['_INFO2_']
            # 检查参数格式,是否按英文逗号分割数字
            if checkSizeList(sizeList):
                # 将其转为列表list
                listSize = sizeList.split(",")

                # 校验参数值是否正确
                valFlg = True
                start_num = 1
                for num in listSize:
                    if (int(num) < start_num):
                        # 如果参数值不正确,校验数值是否正确:一个比一个大
                        valFlg = False
                        info = '指定页码需大于1,且越来越大。'
                        infoDialog(info)
                        break
                    elif (int(num) > pageCount):
                        # 如果参数值不正确,最大的数不能大于pageCount
                        valFlg = False
                        info = '最大的指定页码不能超过总页数({})。'.format(pageCount)
                        infoDialog(info)
                        break
                    start_num = int(num) + 1
                start_num = 1
                if(valFlg):
                    #如果参数值正确,则允许分割
                    # 提示是否执行分割
                    splitInfo = []
                    for num in listSize:
                        splitInfo.append(str(start_num) + '-' + str(num))
                        start_num = int(num) + 1
                    info = '源文件总计%s页,可以分割成%s份文件:%s。\r\n\r\n是否分割PDF文件?' % (pageCount, len(listSize), splitInfo)
                    rtn = nextDialog(info)
                    if(rtn is not None and '分割' == rtn.strip()):
                        # 点击了分割按钮
                        # 执行分割文件
                        inputPathFile = values['_INPUT_PATH_FILE_']
                        inputPath = os.path.abspath(os.path.dirname(inputPathFile) + os.path.sep + ".")
                        inputFile = os.path.splitext(os.path.basename(inputPathFile))[0].split('.')[0]
                        outputPath = '{}\\{}'.format(inputPath, inputFile)
                        # 创建输出文件夹,先判断是否存在,存在则不创建,不存在则新建,使用源文件名称作为文件夹名称
                        try:
                            if(not os.path.exists(outputPath)):
                                os.mkdir(outputPath)
                        except OSError:
                            # 创建输出文件夹失败
                            rtn = exceptionDialog('创建输出文件夹失败!\r\n\r\n异常信息:%s' % OSError)
                            if (rtn is not None and '复制异常信息' == rtn.strip()):
                                pyperclip.copy(exceptionInfo)
                                continue
                            else:
                                continue
                        rtn = pdfSplitOp2(inputPathFile, outputPath, listSize)
                        if('success' == rtn):
                            rtn = openFolderDialog('分割成功!\r\n\r\n是否打开文件夹?\t\t\t\t\t')
                            if(rtn is not None and '打开' == rtn.strip()):
                                os.system("explorer.exe %s" % outputPath)
                            else:
                                continue
                        else:
                            exceptionInfo = rtn
                            rtn = exceptionDialog('执行失败!\r\n\r\n异常信息:%s' % exceptionInfo)
                            if (rtn is not None and '复制异常信息' == rtn.strip()):
                                pyperclip.copy(exceptionInfo)
                                continue
                            else:
                                continue
                        continue
                    elif(rtn is not None and '取消' == rtn.strip()):
                        # 点击了取消按钮
                        continue
                    else:
                        # 点击了标题栏的关闭(X)
                        continue
            else:
                # 如果参数格式不正确
                info = '请输入正确的指定页码(如:3,10,27)。'
                infoDialog(info)
                continue
    elif event == sg.WIN_CLOSED or event == '_CANCEL_':
        break

window.close()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容