PDF分割合并

提取指定页面并合到一起,输出到代码目录下

import os
import time
from PyPDF2 import PdfReader, PdfWriter

def extract_pages(pdf_path, page_numbers):
    # 创建PdfReader对象
    pdf_reader = PdfReader(open(pdf_path, "rb"))

    # 创建PdfWriter对象
    pdf_writer = PdfWriter()

    # 提取并合并指定页面
    try:
        for page_number in page_numbers:
            page = pdf_reader.pages[page_number - 1]  # 页面索引从0开始
            pdf_writer.add_page(page)
    except Exception as e:
        print(f"提取页面时发生错误: {e}")
        raise  # 保留异常,让程序终止

    return pdf_writer

def save_pdf(pdf_writer, output_path, increment=False):
    # 检查文件是否存在并询问用户是否替换或加编号
    while os.path.exists(output_path):
        response = input(f"文件 {output_path} 已存在,是否替换?(y或者回车) 或 输入 'n' 自动添加编号:").lower()
        if response == "y" or response == "":
            break
        elif response == "n":
            increment = True
            break
        else:
            print("无效输入,请重新选择。")

    if increment:
        base_name, ext = os.path.splitext(output_path)
        i = 1
        while os.path.exists(output_path):
            output_path = f"{base_name}_{i}{ext}"
            i += 1

    # 保存PDF文件
    with open(output_path, "wb") as out_file:
        pdf_writer.write(out_file)

def format_page_range_string(page_numbers):
    page_numbers.sort()  # 确保页码有序
    continuous_ranges = []

    current_start = page_numbers[0]
    current_end = page_numbers[0]

    for num in page_numbers[1:]:
        if num == current_end + 1:  # 如果当前页码与前一页面连续
            current_end = num  # 更新当前范围的结束页码
        else:  # 当前页码与前一页面不连续,开始新的范围
            continuous_ranges.append((current_start, current_end))
            current_start = current_end = num

    # 添加最后一个范围
    continuous_ranges.append((current_start, current_end))

    # 将连续范围转换为字符串形式并连接
    formatted_ranges = [f"{start}-{end}" if start != end else str(start) for start, end in continuous_ranges]
    return ",".join(formatted_ranges)

def parse_page_range(page_range_str):
    ranges = []
    for part in page_range_str.split(","):
        if "-" in part:
            start, end = map(int, part.split("-"))
            ranges.extend(range(start, end + 1))
        else:
            ranges.append(int(part))
    return sorted(ranges)

def list_pdf_files(directory):
    pdf_files = []
    for file in os.listdir(directory):
        if file.lower().endswith('.pdf'):
            pdf_files.append(file)
    return pdf_files

def prompt_to_continue():
    print("提取完成,是否继续提取?(回车继续/任意键退出)")
    user_input = input().strip()
    return user_input == ""

def main():
    # 获取用户选择的PDF文件
    directory = input("请输入当前目录路径或输入 'L/回车' 列出当前目录下的PDF文件:")
    if directory.lower() == 'l' or directory.lower() == "":
        pdf_files = list_pdf_files(os.getcwd())
        print("当前目录下的PDF文件:")
        for i, file in enumerate(pdf_files, start=1):
            print(f"{i}. {file}")
        selection = input("请选择一个PDF文件(输入序号):")
        if not selection.isdigit() or int(selection) < 1 or int(selection) > len(pdf_files):
            print("无效的选择,请输入有效的序号。")
            return
        pdf_path = os.path.join(os.getcwd(), pdf_files[int(selection) - 1])
    else:
        pdf_path = directory
        while not os.path.isfile(pdf_path):
            print("文件不存在,请检查路径是否正确。")
            pdf_path = input("请重新输入当前目录路径或输入 'L' 列出当前目录下的PDF文件:")
            if pdf_path.lower() == 'l':
                pdf_files = list_pdf_files(os.getcwd())
                print("当前目录下的PDF文件:")
                for i, file in enumerate(pdf_files, start=1):
                    print(f"{i}. {file}")
                selection = input("请选择一个PDF文件(输入序号):")
                if not selection.isdigit() or int(selection) < 1 or int(selection) > len(pdf_files):
                    print("无效的选择,请输入有效的序号。")
                    return
                pdf_path = os.path.join(os.getcwd(), pdf_files[int(selection) - 1])
                break

    # 获取用户选择的打印类型
    print_types = {
        "1": "黑白单面",
        "2": "黑白双面",
        "3": "彩色单面",
        "4": "彩色双面"
    }
    for key, value in print_types.items():
        print(f"{key}. {value}")
    while True:
        print_type = input("请选择打印类型(输入数字):")
        if print_type in print_types:
            break
        print("无效的打印类型,请输入正确的数字。")

    # 获取用户输入的页面范围
    while True:
        page_range = input("请输入需要提取的页面范围(例如:1,2-5):")
        try:
            page_numbers = parse_page_range(page_range)
            break
        except Exception as e:
            print(f"输入的页面范围格式错误,请输入例如:1,2-5。错误信息:{e}")

    formatted_page_range = format_page_range_string(page_numbers)

    # 提取指定页面
    pdf_writer = extract_pages(pdf_path, page_numbers)

    # 根据打印类型和页面范围命名输出文件
    output_dir, output_file = os.path.split(pdf_path)
    output_name = f"{os.path.splitext(output_file)[0]}_{print_types[print_type]}_{formatted_page_range}.pdf"
    output_path = os.path.join(output_dir, output_name)

    # 保存PDF文件
    save_pdf(pdf_writer, output_path)

    # 提示用户是否继续
    if prompt_to_continue():
        main()  # 重新调用main函数

    print("等待10秒后自动退出...")
    time.sleep(10)

if __name__ == "__main__":
    main()

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

低代码开发之腾讯云微搭工具

低代码开发之腾讯云微搭工具 微搭简介诞生缘由开发模式如何创建组件模块介绍实例讲解url传参级联联动使用事件其他方法调用数据源方法 callDataSource触发流程 callProcess 引入外部css/js代码编辑器的使用Handler 方法使用介绍Style 用法示例LifeCycle 生命周期介绍 数据模型方…

【1471】java项目进度管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java 项目进度管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

测试必备 | 测试工程师必知的Linux命令有哪些?

在日常的测试工作中&#xff0c;涉及到测试环境搭建及通过查看日志来定位相关问题时经常会用到Linux&#xff0c;在测试工程师的面试中也经常会有笔试或面试的题目来考查测试人员对Linux的熟悉程度&#xff0c;这里分享下测试工程师需知的 Linux 命令有哪些。 Linux 作为一种常…

【 书生·浦语大模型实战营】作业(四):XTuner 微调 LLM:1.8B、多模态、Agent

【 书生浦语大模型实战营】作业&#xff08;五&#xff09;&#xff1a;LMDeploy 量化部署 &#x1f389;AI学习星球推荐&#xff1a; GoAI的学习社区 知识星球是一个致力于提供《机器学习 | 深度学习 | CV | NLP | 大模型 | 多模态 | AIGC 》各个最新AI方向综述、论文等成体系…

模块四:前缀和——DP35 【模板】二维前缀和

文章目录 题目描述算法原理解法一&#xff1a;暴力模拟&#xff08;时间复杂度为O(n*m*q)&#xff09;解法二&#xff1a;二维前缀和&#xff08;时间复杂度为O(m*n)O(q)) 代码实现解法二&#xff1a;前缀和&#xff08;C)Java 题目描述 题目链接&#xff1a;DP35 【模板】二维…

微信第三方开放平台,实现代公众号保留排版样式和图片发布文章

大家好&#xff0c;我是小悟 要想实现代公众号发布文章的功能&#xff0c;就得接入富文本编辑器&#xff0c;市面上富文本编辑器有很多&#xff0c;轻量的、重量的都有。 从开发者的角度&#xff0c;自然把轻量作为第一选择&#xff0c;因为好对接&#xff0c;怎么方便怎么来…

基于 SpringCloud 的在线交易平台乐优商城的设计与实现(六)

目录 第六章 系统测试 6.1 功能性测试 6.1.1 商家后台功能测试 6.1.2 前台功能测试 6.2 非功能性测试 6.3 本章小结 结束语 参考文献 前面内容请移步 基于 SpringCloud 的在线交易平台乐优商城的设计与实现&#xff08;五&#xff09; 相关免费源码资源 乐优商城…

2024年【制冷与空调设备运行操作】最新解析及制冷与空调设备运行操作免费试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 制冷与空调设备运行操作最新解析是安全生产模拟考试一点通生成的&#xff0c;制冷与空调设备运行操作证模拟考试题库是根据制冷与空调设备运行操作最新版教材汇编出制冷与空调设备运行操作仿真模拟考试。2024年【制冷…

不只有 Spring,这四款Java 基础开发框架同样值得关注!

Java 开发不只有 Spring &#xff0c;今天给大家推荐几个同样优秀的 Java 基础开发框架&#xff0c;为日常项目开发提供更多的选择。答应我&#xff0c;请不要再叫我 Spring 小子了&#xff0c;​好吗&#xff1f; 项目概览&#xff1a; Guice&#xff1a;轻量级依赖注入框架 …

构建本地大语言模型知识库问答系统

MaxKB 2024 年 4 月 12 日&#xff0c;1Panel 开源项目组正式对外介绍了其官方出品的开源子项目 ——MaxKB&#xff08;github.com/1Panel-dev/MaxKB&#xff09;。MaxKB 是一款基于 LLM&#xff08;Large Language Model&#xff09;大语言模型的知识库问答系统。MaxKB 的产品…

Intelij Idea Push失败,出现git Authentication failed(验证失败)

目录 1、出现问题的原因 2、解决之法 1、出现问题的原因 能出现这种问题&#xff0c;最主要的原因是链接对上了&#xff0c;但用户验证失败了&#xff0c;即登录失败。 因为服务器转移或者换了git项目链接&#xff0c;导致你忘记了用户名密码&#xff0c;随意输入之后&…

P44,45 属性预处理,执行后游戏效果回调,附录指定区域内修改变量

这节课主要是怎么对Attribute进行在进行到游戏角色前先进行处理,以及游戏效果如何回调 AuraAttributeSet.h // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h" #include "AttributeSet.h&…

如何禁用WordPress的自动更新(包括主题、插件和核心文件)

这几天发现我的一个网站突然打不开了&#xff0c;提示“此站点遇到了致命错误”,如图&#xff1a; 这个网站一直都是正常运行的&#xff0c;最近也没有过什么更新&#xff0c;按理说不应该会出现问题&#xff0c;我担心可能是主机方面做了什么调整导致&#xff0c;所以联系了Ho…

品鉴中的个人偏好:如何找到适合自己的红酒风格

品鉴红酒时&#xff0c;个人偏好起着至关重要的作用。不同的人对红酒的风格、口感和特点有着不同的喜好和需求。对于云仓酒庄雷盛红酒而言&#xff0c;如何找到适合自己的红酒风格&#xff0c;是品鉴过程中需要关注的问题。 首先&#xff0c;了解自己的口味和喜好是找到适合自己…

spi接口的基本概念、引脚定义及注意事项

目录 基本概念 引脚定义 注意事项 SPI&#xff08;Serial Peripheral Interface&#xff09;是一种同步串行接口技术&#xff0c;广泛应用于微控制器和各种外围设备之间的短距离通信。 基本概念 SPI接口允许微控制器以串行方式与一个或多个外围设备进行通信。它是一种高速、…

B端:销售投入远超研发投入,想让B端漂亮体验好,非常难。

足够的研发费用是确保B端系统研发体验好、品质佳的重要条件之一。在B端系统研发过程中&#xff0c;足够的研发费用可以用于以下方面&#xff1a; 1.人才投入&#xff1a; 招聘高素质的研发团队成员&#xff0c;包括开发工程师、测试工程师、产品设计师、运维工程师等&#xf…

【进程通信】利用管道创建进程池(结合代码)

文章目录 什么叫进程池进程池的优点 创建进程池代码实现&#xff1a; 什么叫进程池 我们知道&#xff0c;一个进程创建子进程通常是为了让这个子进程去为它完成某个任务。例如我们使用的指令&#xff0c;其实就是bash进程创建子进程让子进程去执行的。但是我们需要考虑这样一个…

RLDP协议原理与应用

RLDP概述 l RLDP全称是Rapid Link Detection Protocol&#xff08;快速链路检测协议&#xff09;&#xff0c;是锐捷网络自主开发的&#xff0c;用于快速检测以太网链路故障的链路协议。 l 一般的以太网链路检测机制都只是利用物理连接的状态&#xff0c;通过物理层的自动协…

React | classnames

classnames 这个库在我们的项目中有大量的使用到&#xff0c;它不仅很实用&#xff0c;还非常好用&#xff0c;但还有人不知道这个库&#xff0c;我真的是十分心痛。 通过 classnames&#xff0c;我们可以给组件设置多个 className&#xff0c;还可以根据需要动态设置 classNa…

机器学习中的CatBoost算法

我们经常遇到包含分类特征的数据集&#xff0c;为了将这些数据集拟合到Boosting模型中&#xff0c;我们对数据集应用各种编码技术&#xff0c;例如One-Hot编码或标签编码。但是应用One-Hot编码会创建一个稀疏矩阵&#xff0c;这有时可能导致模型的过拟合&#xff0c;我们使用Ca…
最新文章