Python-07PDF转Word

news2025/4/24 0:28:23

2025-03-04-PDF转Word

DeepSeek等大模型从来都不是简单的写一个静态博客这么肤浅(太多博主都只讲这个内容了)借助全网大神的奇思妙想,拓展我狭隘的思维边界。


文章目录

  • 2025-03-04-PDF转Word
    • @[toc]
    • 1-参考网址
    • 2-学习要点
    • 3-核心逻辑
    • 4-核心代码

1-参考网址

  • DeepSeek编写一个PDF转Word软件(参考当前):https://blog.csdn.net/henanlion/article/details/145861672
  • 个人尝试代码仓库:https://gitee.com/enzoism/pdf2word

2-学习要点

  • 1)思维拓展-DeepSeek如何辅助编程
  • 2)Python-编写PDF转Word:https://blog.csdn.net/2301_77717148/article/details/146015704
  • 3)Python-使用tkinter:https://blog.csdn.net/2301_77717148/article/details/146015225
  • 4)Python-使用threading和queue:https://blog.csdn.net/2301_77717148/article/details/146013352
  • 5)Python-编写Requirements.txt:https://blog.csdn.net/2301_77717148/article/details/146012907

3-核心逻辑

  • 1)使用pdf2docx库将PDF文件转换为Word文件
  • 2)使用tkinter实现GUI界面
  • 3)使用threading和queue实现多线程和消息队列通信
  • 4)使用Requirements.txt管理依赖库

4-核心代码

  • DeepSeek编写一个PDF转Word软件(参考当前):https://blog.csdn.net/henanlion/article/details/145861672
import os
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from pdf2docx import Converter
import threading
import queue


class PDFToWordConverter:
    def __init__(self, master):
        self.master = master
        master.title("PDF批量转Word")
        master.geometry("610x295")

        # 输入文件夹
        self.lbl_input = tk.Label(master, text="输入文件夹:")
        self.ent_input = tk.Entry(master, width=30)
        self.btn_input = tk.Button(master, text="选择", command=self.select_input)

        # 输出文件夹
        self.lbl_output = tk.Label(master, text="输出文件夹:")
        self.ent_output = tk.Entry(master, width=30)
        self.btn_output = tk.Button(master, text="选择", command=self.select_output)

        # 复选框
        self.var_subdir = tk.BooleanVar()
        self.var_open = tk.BooleanVar(value=True)
        self.chk_subdir = tk.Checkbutton(master, text="包含子文件夹", variable=self.var_subdir)
        self.chk_open = tk.Checkbutton(master, text="转换完成后打开目标文件夹", variable=self.var_open)

        # 转换按钮
        self.btn_convert = tk.Button(master, text="开始转换", command=self.start_conversion)

        # 布局
        self.lbl_input.grid(row=0, column=0, padx=10, pady=10, sticky=tk.W)
        self.ent_input.grid(row=0, column=1, padx=5, pady=10, sticky=tk.EW)
        self.btn_input.grid(row=0, column=2, padx=10, pady=10)

        self.lbl_output.grid(row=1, column=0, padx=10, pady=10, sticky=tk.W)
        self.ent_output.grid(row=1, column=1, padx=5, pady=10, sticky=tk.EW)
        self.btn_output.grid(row=1, column=2, padx=10, pady=10)

        self.chk_subdir.grid(row=2, column=1, padx=5, pady=5, sticky=tk.W)
        self.chk_open.grid(row=3, column=1, padx=5, pady=5, sticky=tk.W)

        self.btn_convert.grid(row=4, column=1, pady=10)

        # 新增进度组件
        self.progress_label = tk.Label(master, text="准备就绪")
        self.progress_bar = ttk.Progressbar(master, orient=tk.HORIZONTAL, mode='determinate')

        # 调整布局(新增两行)
        self.progress_label.grid(row=5, column=0, columnspan=3, padx=10, pady=5, sticky=tk.W)
        self.progress_bar.grid(row=6, column=0, columnspan=3, padx=10, pady=10, sticky=tk.EW)

        # 消息队列用于线程通信
        self.queue = queue.Queue()
        master.after(100, self.process_queue)

        # 配置列权重
        master.columnconfigure(1, weight=1)

    def select_input(self):
        path = filedialog.askdirectory()
        if path:
            self.ent_input.delete(0, tk.END)
            self.ent_input.insert(0, path)

    def select_output(self):
        path = filedialog.askdirectory()
        if path:
            self.ent_output.delete(0, tk.END)
            self.ent_output.insert(0, path)

    def start_conversion(self):
        # 重置进度条
        self.progress_bar['value'] = 0
        self.progress_label.config(text="正在扫描PDF文件...")

        input_dir = self.ent_input.get()
        output_dir = self.ent_output.get()

        if not input_dir or not output_dir:
            messagebox.showerror("错误", "请先选择输入和输出文件夹!")
            return
        # 禁用转换按钮
        self.btn_convert.config(state=tk.DISABLED)

        threading.Thread(target=self.convert_files, args=(input_dir, output_dir), daemon=True).start()

    def get_pdf_list(self, input_dir):
        pdf_list = []
        for root, dirs, files in os.walk(input_dir):
            if not self.var_subdir.get() and root != input_dir:
                continue
            for file in files:
                if file.lower().endswith('.pdf'):
                    pdf_list.append(os.path.join(root, file))
        return pdf_list

    def convert_files(self, input_dir, output_dir):
        self.pdf_files = self.get_pdf_list(input_dir)
        try:
            total_files = len(self.pdf_files)
            for index, pdf_path in enumerate(self.pdf_files):
                # 更新当前文件进度
                self.queue.put(("file_progress", (index + 1, total_files, pdf_path)))

                # 构建输出路径
                relative_path = os.path.relpath(os.path.dirname(pdf_path), input_dir) if self.var_subdir.get() else ""
                output_path = os.path.join(output_dir, relative_path)
                os.makedirs(output_path, exist_ok=True)

                # 转换文件
                docx_path = os.path.join(output_path, f"{os.path.splitext(os.path.basename(pdf_path))[0]}.docx")
                cv = Converter(pdf_path)
                cv.convert(docx_path, progress_callback=self.update_page_progress)
                cv.close()

            self.queue.put(("complete", None))
        except Exception as e:
            self.queue.put(("error", str(e)))

    def update_page_progress(self, current, total):
        # 页面级别进度(每文件0-100%)
        progress = (current / total) * 100 if total != 0 else 0
        self.queue.put(("page_progress", progress))

    def process_queue(self):
        try:
            while True:
                msg_type, data = self.queue.get_nowait()

                if msg_type == "file_progress":
                    current, total, path = data
                    file_progress = (current / total) * 100
                    self.progress_bar['value'] = file_progress
                    self.progress_label.config(text=f"正在转换 {current}/{total}{os.path.basename(path)}")

                elif msg_type == "page_progress":
                    # 综合进度 = 文件进度 + 页面进度/总文件数
                    current_file_progress = self.progress_bar['value']
                    page_progress = data / len(self.pdf_files)
                    self.progress_bar['value'] = current_file_progress + page_progress

                elif msg_type == "complete":
                    messagebox.showinfo("完成", "转换完成!")
                    if self.var_open.get():
                        os.startfile(self.ent_output.get())
                    self.btn_convert.config(state=tk.NORMAL)
                    self.progress_label.config(text="转换完成")

                elif msg_type == "error":
                    messagebox.showerror("错误", f"转换出错:{data}")
                    self.btn_convert.config(state=tk.NORMAL)
                    self.progress_label.config(text="转换出错")

        except queue.Empty:
            pass
        finally:
            self.master.after(100, self.process_queue)


if __name__ == "__main__":
    root = tk.Tk()
    app = PDFToWordConverter(root)
    root.mainloop()

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Arcgis中添加脚本工具箱

文章目录 准备资料1、打开arcmap2、找到目录窗口3、复制粘贴工具箱的路径4、添加或者确认python脚本路径准备资料 (1)工具箱 (2)python脚本 1、打开arcmap 2、找到目录窗口 3、复制粘贴工具箱的路径 4、添加或者确认python脚本路径 脚本上右键属性(注意:脚本内容和路径…

拥抱健康养生,开启活力生活

在快节奏的现代生活中,健康养生已成为人们关注的焦点,它不仅是对身体的呵护,更是一种积极的生活态度。 合理饮食是健康养生的基石。我们应秉持均衡膳食的理念,谷物、蔬菜、水果、蛋白质类食物一个都不能少。每天保证足够的蔬菜摄入…

字节跳动AI原生编程工具Trae和百度“三大开发神器”AgentBuilder、AppBuilder、ModelBuilder的区别是?

字节跳动AI编程工具Trae与百度"三大开发神器"(AgentBuilder、AppBuilder、ModelBuilder)在定位、功能架构和技术路线上存在显著差异,具体区别如下: 一、核心定位差异 Trae:AI原生集成开发环境(AI…

【MySQL】第十二弹---表连接详解:从内连接到外连接

✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】【MySQL】 目录 1.表的内连和外连 1.1 内连接 1.2 外连接 1.2.1 左外连接 1.2.1 右外连接 1.3 实战OJ 1.表的内连和外连 表的连接…

审批流AntV框架蚂蚁数据可视化X6饼图(附注释)

大家好,这次使用的是AntV的蚂蚁数据可视化X6框架,类似于审批流的场景等,代码如下: X6框架参考网址:https://x6.antv.vision/zh/examples/showcase/practices#bpmn 可以进入该网址,直接复制下方代码进行调试…

【SpringBoot】深入解析 Maven 的操作与配置

Maven 1.什么是Maven? Maven是一个项目管理工具,通过pom.xml文件的配置获取jar包,而不用手动去添加jar包; 2. 创建一个Maven项目 IDEA本身已经集成了Maven,我们可以直接使用,无需安装 以下截图的idea版本为&#xff…

搭建一个简单的node服务,模拟后端接口

目录 一、查看是否安装了node和npm 二、创建一个文件夹,用于放你的node服务代码 三、初始化一个package.json 四、安装 Express(快速搭建服务的框架) 五、创建serve.js 六、运行服务即可 七、测试接口 法一:使用 curl 法…

【落羽的落羽 C++】C++入门基础:引用,内联,nullptr

文章目录 一、引用1. 引用的概念2. 引用的特点3. 引用的使用4. const引用5. 引用和指针 二、inline内联三、nullptr 一、引用 1. 引用的概念 引用是C中的一个较为重要的概念。它是给已存在变量取的“别名”,编译器不会为引用变量开辟内存空间,它和它引…

Python的那些事第四十一篇:简化数据库交互的利器Django ORM

Django ORM:简化数据库交互的利器 摘要 随着互联网技术的飞速发展,Web开发越来越受到重视。Django作为一款流行的Python Web框架,以其高效、安全、可扩展等特点受到了广大开发者的喜爱。其中,Django ORM(对象关系映射)是Django框架的核心组件之一,它为开发者提供了一种…

通过多线程同时获取H264和H265码流

目录 一.RV1126 VI采集摄像头数据并同时编码H264、H265的大概流程​编辑​编辑 1.1初始化VI模块: 1.2H264、H265的VENC模块初始化: 1.3VI分别绑定H264的VENC层和H265的VENC层: ​​​​​​​1.4开启H264线程采集H264的VENC数据&#xff…

DeepSeek V3 源码:从入门到放弃!

从入门到放弃 花了几天时间,看懂了DeepSeek V3 源码的逻辑。源码的逻辑是不难的,但为什么模型结构需要这样设计,为什么参数需要这样设置呢?知其然,但不知其所以然。除了模型结构以外,模型的训练数据、训练…

海量数据融合互通丨TiDB 在安徽省住房公积金监管服务平台的应用实践

导读 安徽省住房公积金监管服务平台通过整合全省 17 家公积金中心的数据,致力于实现数据共享、规范化管理与高效数据分析。为了应对海量数据处理需求,安徽省选择 TiDB 作为底层数据库,利用其分布式架构和 HTAP 能力,实现了快速的…

Linux12-UDP\TCP

一、UDP 1.特点: 尽最大努力交付,存在丢包的可能 无连接 面向数据报 机制简单,传输效率高 2.应用场景: 1.画面传输 VNC 直播:要求实时性高、允许数据丢失、 二、TCP 1.特点: 面向数据流(流式套接字) 建立连接 安全可靠的传输协议 三次握手:TCP建立连接时,…

【HeadFirst系列之HeadFirst设计模式】第14天之与设计模式相处:真实世界中的设计模式

与设计模式相处:真实世界中的设计模式 设计模式是软件开发中的经典解决方案,它们帮助我们解决常见的设计问题,并提高代码的可维护性和可扩展性。在《Head First设计模式》一书中,作者通过生动的案例和通俗的语言,深入…

自由学习记录(42)

可能会出现到后面没有教程可以看,走不动,,但还是尝试吧 过程远比想象的要多 那连Live2d的这些脚本怎么控制的都要了解一下 ------------ 文件类型和扩展名 | 编辑手册 | Live2D Manuals & Tutorials 全部导入之后 在这下载SDK Live2D…

excel vlookup的精确查询、模糊查询、反向查询、多列查询

目录 入门 精确查询 模糊查询 反向查询 (搭配 if 函数) 多列查询 (搭配 match 函数) 入门 精确查询 需求: 查找 学生编号是008 所在的班级 操作: 在I2单元格输入公式如下,VLOOKUP(H2,B1:E12,4,FALSE), 得出结果 看一下vlookup 公式每一个参数应该怎么写? 语法: vlookup…

安装remixd,在VScode创建hardhat

在终端,以管理员身份,cmd 需要科学上网 npm install -g remix-project/remixd 在vscode插件中,安装solidity插件,是暗灰色那款 1.将nodeJs的版本升级至18以上 2.在vscode打开一个新的文件,在终端输入 npx hardhat 3.…

【Python爬虫】利用代理IP爬取跨境电商AI选品分析

引言 随着DeepSeek的流行,越来越多的用户开始尝试将AI工具融入到日常工作当中,借助AI的强大功能提高工作效率。最近又掀起了一波企业出海的小高潮,那么如果是做跨境电商业务,怎么将AI融入工作流中呢?在做跨境电商的时候…

捣鼓180天,我写了一个相册小程序

🙋为什么要做土著相册这样一个产品? ➡️在高压工作之余,我喜欢浏览B站上的熊猫幼崽视频来放松心情。有天在家族群里看到了大嫂分享的侄女卖萌照片,同样感到非常解压。于是开始翻阅过去的聊天记录,却发现部分图片和视…

洛谷 P1480 A/B Problem(高精度详解)c++

题目链接:P1480 A/B Problem - 洛谷 1.题目分析 1:说明这里是高精度除以低精度的形式,为什么不是高精度除以高精度的形式,是因为它很少见,它的模拟方式是用高精度减法来做的,并不能用小学列竖式的方法模拟…