吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2143|回复: 6
收起左侧

[Python 转载] svg批量转换pdf(python源码)

  [复制链接]
钱途迷茫 发表于 2025-9-18 22:15
本帖最后由 钱途迷茫 于 2025-9-19 14:44 编辑

一些svg想转成pdf,网上找了一下,基本上都是在线版,转换好后下载速度极慢,于是想起了万能的豆包,写了一个python程序,用着还不错
自己能力有限,希望热心的大佬大忙打包成exe文件给大家用起来方便一些
wechat_2025-09-18_221403_358.png
exe版下载(感谢沙发的打包)
蓝奏云https://wwrz.lanzout.com/iSo0k36juu3c
百度云https://pan.baidu.com/s/1YFFh7MEh0WNDg3F8Vl2i8A 提取码: j2wu

[Python] 纯文本查看 复制代码
import os
import re
import tkinter as tk
from tkinter import filedialog, ttk, scrolledtext
from svglib.svglib import svg2rlg
from reportlab.graphics import renderPDF
import threading


class SVGToPDFConverter:
    def __init__(self, root):
        self.root = root
        self.root.title("SVG到PDF批量转换器")
        self.root.geometry("700x500")
        self.root.resizable(True, True)

        # 设置中文字体支持
        self.style = ttk.Style()
        self.style.configure("TLabel", font=("SimHei", 10))
        self.style.configure("TButton", font=("SimHei", 10))
        self.style.configure("TEntry", font=("SimHei", 10))

        # 源文件夹路径
        self.source_dir = tk.StringVar()
        # 输出文件夹路径
        self.output_dir = tk.StringVar()

        self.create_widgets()

    def create_widgets(self):
        # 创建主框架
        main_frame = ttk.Frame(self.root, padding="20")
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 源文件夹选择
        ttk.Label(main_frame, text="SVG源文件夹:").grid(row=0, column=0, sticky=tk.W, pady=5)
        ttk.Entry(main_frame, textvariable=self.source_dir, width=50).grid(row=0, column=1, pady=5)
        ttk.Button(main_frame, text="浏览...", command=self.select_source_dir).grid(row=0, column=2, padx=5, pady=5)

        # 输出文件夹选择
        ttk.Label(main_frame, text="PDF输出文件夹:").grid(row=1, column=0, sticky=tk.W, pady=5)
        ttk.Entry(main_frame, textvariable=self.output_dir, width=50).grid(row=1, column=1, pady=5)
        ttk.Button(main_frame, text="浏览...", command=self.select_output_dir).grid(row=1, column=2, padx=5, pady=5)

        # 转换按钮
        ttk.Button(main_frame, text="开始转换", command=self.start_conversion).grid(row=2, column=0, columnspan=3,
                                                                                    pady=10)

        # 进度条
        self.progress_var = tk.DoubleVar()
        self.progress_bar = ttk.Progressbar(main_frame, variable=self.progress_var, maximum=100)
        self.progress_bar.grid(row=3, column=0, columnspan=3, sticky=tk.EW, pady=5)

        # 状态文本框
        ttk.Label(main_frame, text="转换状态:").grid(row=4, column=0, sticky=tk.NW, pady=5)
        self.status_text = scrolledtext.ScrolledText(main_frame, width=60, height=15, wrap=tk.WORD)
        self.status_text.grid(row=4, column=1, columnspan=2, pady=5, sticky=tk.NSEW)

        # 配置网格权重,使控件可以随窗口大小调整
        main_frame.columnconfigure(1, weight=1)
        main_frame.rowconfigure(4, weight=1)

    def select_source_dir(self):
        dir_path = filedialog.askdirectory(title="选择SVG源文件夹")
        if dir_path:
            self.source_dir.set(dir_path)

    def select_output_dir(self):
        dir_path = filedialog.askdirectory(title="选择PDF输出文件夹")
        if dir_path:
            self.output_dir.set(dir_path)

    def log(self, message):
        """在状态文本框中添加日志信息"""
        self.status_text.insert(tk.END, message + "\n")
        self.status_text.see(tk.END)  # 滚动到最后一行

    def preprocess_svg(self, svg_path, temp_path, default_color="#000000"):
        """预处理SVG文件,替换url()颜色引用"""
        try:
            with open(svg_path, 'r', encoding='utf-8') as f:
                svg_content = f.read()

            # 替换颜色引用为默认颜色
            svg_content = re.sub(r'url\(#.*?\)', default_color, svg_content)

            with open(temp_path, 'w', encoding='utf-8') as f:
                f.write(svg_content)

            return True
        except Exception as e:
            self.log(f"SVG预处理失败: {str(e)}")
            return False

    def svg_to_pdf(self, svg_file_path, pdf_file_path, use_preprocessing=True):
        """将单个SVG文件转换为PDF文件,可选择预处理"""
        temp_svg = None
        try:
            # 如果需要预处理且包含url颜色引用
            if use_preprocessing:
                with open(svg_file_path, 'r', encoding='utf-8') as f:
                    content = f.read()
                if 'url(#)' in content:
                    temp_svg = f"temp_{os.path.basename(svg_file_path)}"
                    if not self.preprocess_svg(svg_file_path, temp_svg):
                        return False
                    svg_path = temp_svg
                else:
                    svg_path = svg_file_path
            else:
                svg_path = svg_file_path

            drawing = svg2rlg(svg_path)
            renderPDF.drawToFile(drawing, pdf_file_path)
            return True
        except Exception as e:
            self.log(f"转换错误: {str(e)}")
            return False
        finally:
            # 清理临时文件
            if temp_svg and os.path.exists(temp_svg):
                try:
                    os.remove(temp_svg)
                except:
                    pass

    def batch_convert(self):
        """批量转换函数,在单独线程中运行"""
        svg_dir = self.source_dir.get()
        pdf_dir = self.output_dir.get()

        # 验证文件夹路径
        if not svg_dir or not os.path.isdir(svg_dir):
            self.log("请选择有效的SVG源文件夹")
            self.progress_var.set(0)
            return

        if not pdf_dir or not os.path.isdir(pdf_dir):
            self.log("请选择有效的PDF输出文件夹")
            self.progress_var.set(0)
            return

        # 获取所有SVG文件
        svg_files = []
        for filename in os.listdir(svg_dir):
            if filename.lower().endswith('.svg') and os.path.isfile(os.path.join(svg_dir, filename)):
                svg_files.append(filename)

        if not svg_files:
            self.log("在源文件夹中未找到任何SVG文件")
            self.progress_var.set(0)
            return

        total_files = len(svg_files)
        self.log(f"找到 {total_files} 个SVG文件,开始转换...")

        # 逐个转换文件
        success_count = 0
        for i, filename in enumerate(svg_files, 1):
            svg_path = os.path.join(svg_dir, filename)
            pdf_filename = os.path.splitext(filename)[0] + '.pdf'
            pdf_path = os.path.join(pdf_dir, pdf_filename)

            try:
                # 先尝试直接转换
                success = self.svg_to_pdf(svg_path, pdf_path, use_preprocessing=False)

                # 如果失败,尝试使用预处理
                if not success:
                    self.log(f"尝试使用预处理转换 {filename}...")
                    success = self.svg_to_pdf(svg_path, pdf_path, use_preprocessing=True)

                if success:
                    success_count += 1
                    self.log(f"成功转换: {filename} -> {pdf_filename}")
                else:
                    self.log(f"无法转换: {filename}")
            except Exception as e:
                self.log(f"处理 {filename} 时出错: {str(e)}")

            # 更新进度条
            progress = (i / total_files) * 100
            self.progress_var.set(progress)
            self.root.update_idletasks()

        self.log(f"转换完成!成功转换 {success_count}/{total_files} 个文件")
        self.progress_var.set(100)

    def start_conversion(self):
        """开始转换,在新线程中运行以避免界面冻结"""
        # 清空之前的日志
        self.status_text.delete(1.0, tk.END)
        self.progress_var.set(0)

        # 在新线程中运行转换,防止界面冻结
        conversion_thread = threading.Thread(target=self.batch_convert)
        conversion_thread.daemon = True  # 当主线程退出时,子线程也退出
        conversion_thread.start()


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

免费评分

参与人数 3吾爱币 +5 热心值 +3 收起 理由
苏紫方璇 + 3 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
SherlockProel + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
lss655 + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

dkmg 发表于 2025-9-18 23:28
https://www.123684.com/s/PvjA-BXRWh?pwd=Mw9T#
cioceo 发表于 2025-9-19 08:07
感谢原创,我记得论坛有svg转pdf的相关案例,云展部分图片是svg的
SherlockProel 发表于 2025-9-19 10:28
jiuchengyixi 发表于 2025-9-19 11:26
感谢大佬分享
wincoy 发表于 2025-9-19 12:46
厉害了我的哥。
jll0574 发表于 2026-8-31 09:08
转Pdf后中文不显示
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-9-1 02:29

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表