吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6972|回复: 102
收起左侧

[Python 原创] 优酷视频下载工具

  [复制链接]
cxr666 发表于 2025-8-7 19:06
本帖最后由 苏紫方璇 于 2025-8-9 10:10 编辑

无聊翻看吾爱的搜索栏,发现很多人优酷的视频下载都靠别人帮忙,所以自己花下午一点时间就做了这样一个优酷视频下载工具。
用的是you-get,如果没有安装的话打开cmd输入pip install you-get就行(因为作者不会写自动安装这块的代码)
清晰度选“自动选择”不要换,默认的就是高清,不然........你懂的,下载失败我不管的哈。
记得先点获取视频等成功后再下载视频哦。
好了,直接上源码


[Python] 纯文本查看 复制代码
import tkinter as tk
from tkinter import ttk, filedialog, scrolledtext, messagebox
import os
import sys
import threading
import subprocess
import re
from datetime import datetime

class YoukuDownloader:
    def __init__(self, root):
        self.root = root
        self.root.title("优酷视频下载工具")
        self.root.geometry("800x600")
        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.style.configure("TCombobox", font=("SimHei", 10))
        
        # 创建主框架
        self.main_frame = ttk.Frame(root, padding="10")
        self.main_frame.pack(fill=tk.BOTH, expand=True)
        
        # URL输入区域
        self.url_frame = ttk.LabelFrame(self.main_frame, text="视频URL", padding="10")
        self.url_frame.pack(fill=tk.X, pady=5)
        
        self.url_label = ttk.Label(self.url_frame, text="视频地址:")
        self.url_label.pack(side=tk.LEFT, padx=5)
        
        self.url_entry = ttk.Entry(self.url_frame)
        self.url_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        self.url_entry.insert(0, "https://v.youku.com/")
        
        # 输出路径选择区域
        self.path_frame = ttk.LabelFrame(self.main_frame, text="保存设置", padding="10")
        self.path_frame.pack(fill=tk.X, pady=5)
        
        self.path_label = ttk.Label(self.path_frame, text="保存路径:")
        self.path_label.pack(side=tk.LEFT, padx=5)
        
        self.path_entry = ttk.Entry(self.path_frame)
        self.path_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        self.path_entry.insert(0, os.path.expanduser("~/Downloads"))
        
        self.browse_btn = ttk.Button(self.path_frame, text="浏览...", command=self.browse_path)
        self.browse_btn.pack(side=tk.LEFT, padx=5)
        
        # 清晰度选择区域
        self.quality_frame = ttk.LabelFrame(self.main_frame, text="下载设置", padding="10")
        self.quality_frame.pack(fill=tk.X, pady=5)
        
        self.quality_label = ttk.Label(self.quality_frame, text="清晰度:")
        self.quality_label.pack(side=tk.LEFT, padx=5)
        
        self.quality_var = tk.StringVar()
        self.quality_combobox = ttk.Combobox(
            self.quality_frame,
            textvariable=self.quality_var,
            state="readonly",
            width=15
        )
        # 初始选项,后续会根据视频信息更新
        self.quality_combobox['values'] = ["自动选择", "高清", "标清", "流畅"]
        self.quality_combobox.current(0)
        self.quality_combobox.pack(side=tk.LEFT, padx=5)
        
        self.format_label = ttk.Label(self.quality_frame, text="输出格式:")
        self.format_label.pack(side=tk.LEFT, padx=5)
        
        self.format_var = tk.StringVar(value="mp4")
        self.format_combobox = ttk.Combobox(
            self.quality_frame,
            textvariable=self.format_var,
            state="readonly",
            width=10
        )
        self.format_combobox['values'] = ["mp4", "flv", "webm"]
        self.format_combobox.pack(side=tk.LEFT, padx=5)
        
        # 按钮区域
        self.btn_frame = ttk.Frame(self.main_frame, padding="10")
        self.btn_frame.pack(fill=tk.X, pady=5)
        
        self.fetch_btn = ttk.Button(self.btn_frame, text="获取视频信息", command=self.fetch_video_info)
        self.fetch_btn.pack(side=tk.LEFT, padx=5)
        
        self.download_btn = ttk.Button(self.btn_frame, text="开始下载", command=self.start_download)
        self.download_btn.pack(side=tk.LEFT, padx=5)
        
        self.cancel_btn = ttk.Button(self.btn_frame, text="取消下载", command=self.cancel_download)
        self.cancel_btn.pack(side=tk.LEFT, padx=5)
        self.cancel_btn.config(state=tk.DISABLED)
        
        # 日志区域
        self.log_frame = ttk.LabelFrame(self.main_frame, text="日志信息", padding="10")
        self.log_frame.pack(fill=tk.BOTH, expand=True, pady=5)
        
        self.log_text = scrolledtext.ScrolledText(self.log_frame, wrap=tk.WORD, font=("SimHei", 9))
        self.log_text.pack(fill=tk.BOTH, expand=True)
        self.log_text.config(state=tk.DISABLED)
        
        # 下载线程和进程控制
        self.download_thread = None
        self.download_process = None
        self.is_downloading = False
        
        # 初始化日志
        self.log("优酷视频下载工具已启动")
        
    def browse_path(self):
        """选择保存路径"""
        path = filedialog.askdirectory()
        if path:
            self.path_entry.delete(0, tk.END)
            self.path_entry.insert(0, path)
   
    def log(self, message):
        """添加日志信息"""
        self.log_text.config(state=tk.NORMAL)
        timestamp = datetime.now().strftime("%H:%M:%S")
        self.log_text.insert(tk.END, f"[{timestamp}] {message}\n")
        self.log_text.see(tk.END)  # 滚动到最新日志
        self.log_text.config(state=tk.DISABLED)
   
    def fetch_video_info(self):
        """获取视频信息,主要是可用的清晰度"""
        url = self.url_entry.get().strip()
        if not url:
            messagebox.showerror("错误", "请输入视频URL")
            return
        
        self.log("正在获取视频信息...")
        
        # 在新线程中执行,避免UI卡顿
        threading.Thread(target=self._do_fetch_info, args=(url,), daemon=True).start()
   
    def _do_fetch_info(self, url):
        """实际执行获取视频信息的操作"""
        try:
            # 使用you-get查看视频信息
            result = subprocess.run(
                ["you-get", "--info", url],
                capture_output=True,
                text=True,
                encoding="utf-8",
                errors="replace"
            )
            
            output = result.stdout + result.stderr
            self.log("视频信息获取成功")
            
            # 解析输出,提取可用的清晰度
            qualities = []
            # 简单的正则匹配,可能需要根据实际输出调整
            pattern = re.compile(r'\[.*?\] (.*?) .*?(\d+x\d+)')
            matches = pattern.findall(output)
            
            if matches:
                qualities = [f"{q[0]} ({q[1]})" for q in matches]
                # 在UI线程中更新下拉框
                self.root.after(0, self._update_quality_combobox, qualities)
            else:
                self.log("未识别到可用的清晰度信息,使用默认选项")
               
        except Exception as e:
            self.log(f"获取视频信息失败: {str(e)}")
   
    def _update_quality_combobox(self, qualities):
        """更新清晰度选择下拉框"""
        if qualities:
            self.quality_combobox['values'] = ["自动选择"] + qualities
            self.quality_combobox.current(0)
            self.log(f"检测到可用清晰度: {', '.join(qualities)}")
   
    def start_download(self):
        """开始下载视频"""
        url = self.url_entry.get().strip()
        output_path = self.path_entry.get().strip()
        quality = self.quality_var.get()
        output_format = self.format_var.get()
        
        if not url:
            messagebox.showerror("错误", "请输入视频URL")
            return
        
        if not output_path or not os.path.isdir(output_path):
            messagebox.showerror("错误", "请选择有效的保存路径")
            return
        
        self.is_downloading = True
        self.download_btn.config(state=tk.DISABLED)
        self.cancel_btn.config(state=tk.NORMAL)
        self.fetch_btn.config(state=tk.DISABLED)
        
        self.log(f"开始下载视频: {url}")
        self.log(f"保存路径: {output_path}")
        self.log(f"选择清晰度: {quality}")
        self.log(f"输出格式: {output_format}")
        
        # 在新线程中执行下载,避免UI卡顿
        self.download_thread = threading.Thread(
            target=self._do_download,
            args=(url, output_path, quality, output_format),
            daemon=True
        )
        self.download_thread.start()
   
    def _do_download(self, url, output_path, quality, output_format):
        """实际执行下载操作"""
        try:
            # 构建you-get命令
            cmd = [
                "you-get",
                "-o", output_path,
                "-O", f"video.{output_format}",  # 输出文件名
            ]
            
            # 如果不是自动选择,添加清晰度参数
            if quality != "自动选择":
                # 提取清晰度名称
                quality_name = quality.split()[0]
                cmd.extend(["-Q", quality_name])
               
            cmd.append(url)
            
            # 执行下载命令
            self.download_process = subprocess.Popen(
                cmd,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                text=True,
                encoding="utf-8",
                errors="replace"
            )
            
            # 实时输出日志
            for line in self.download_process.stdout:
                if not self.is_downloading:
                    break
                self.log(line.strip())
            
            # 等待进程结束
            self.download_process.wait()
            
            if self.is_downloading:
                if self.download_process.returncode == 0:
                    self.log("视频下载完成!")
                    self.root.after(0, lambda: messagebox.showinfo("成功", "视频下载完成!"))
                else:
                    self.log(f"下载失败,返回代码: {self.download_process.returncode}")
                    self.root.after(0, lambda: messagebox.showerror("失败", "视频下载失败!"))
        
        except Exception as e:
            self.log(f"下载过程中发生错误: {str(e)}")
            self.root.after(0, lambda: messagebox.showerror("错误", f"下载过程中发生错误: {str(e)}"))
        
        finally:
            self.is_downloading = False
            self.root.after(0, self._download_finished)
   
    def _download_finished(self):
        """下载完成后更新UI状态"""
        self.download_btn.config(state=tk.NORMAL)
        self.cancel_btn.config(state=tk.DISABLED)
        self.fetch_btn.config(state=tk.NORMAL)
        self.download_process = None
        self.download_thread = None
   
    def cancel_download(self):
        """取消下载"""
        if self.is_downloading and self.download_process:
            if messagebox.askyesno("确认", "确定要取消下载吗?"):
                self.log("正在取消下载...")
                self.is_downloading = False
                # 终止下载进程
                try:
                    self.download_process.terminate()
                    self.log("下载已取消")
                except Exception as e:
                    self.log(f"取消下载时发生错误: {str(e)}")

if __name__ == "__main__":
    # 检查是否安装了you-get
    try:
        subprocess.run(["you-get", "--version"], capture_output=True, check=True)
    except (subprocess.SubprocessError, FileNotFoundError):
        print("未检测到you-get,请先安装: pip install you-get")
        sys.exit(1)
   
    root = tk.Tk()
    app = YoukuDownloader(root)
    root.mainloop()






最后打包好的:https://wwcq.lanzouu.com/i7ygo32wagrg,没办法作者是初二学生没有会员所以不能设置无密码,密码:52pj,感谢支持!

免费评分

参与人数 27吾爱币 +29 热心值 +25 收起 理由
凡若尘曦 + 1 + 1 动手能力,赞!
SouperGeng + 1 + 1 谢谢@Thanks!
biko + 1 + 1 谢谢@Thanks!
kingstarg + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Leoken + 1 + 1 谢谢@Thanks!
abch891 + 1 我很赞同!
小怪兽出现 + 1 谢谢@Thanks!
w520025 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
gym_168 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
kikou2013 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
YYL7535 + 1 + 1 谢谢@Thanks!
柠檬树上柠檬酸 + 1 + 1 用心讨论,共获提升!
天地和顺 + 2 + 1 谢谢@Thanks!
liu35915362 + 1 热心回复!
棉周 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
w360 + 1 + 1 热心回复!
pengyong50 + 1 + 1 我很赞同!
valen + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
freedomw10 + 1 + 1 谢谢@Thanks!
Msir0214 + 1 我很赞同!
luning + 1 + 1 谢谢@Thanks!
renzhen1997 + 1 + 1 这个必须上分
Cmzlwc + 1 + 1 谢谢@Thanks!
yanglinman + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
hrh123 + 5 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
zephyrcn + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
manglang + 1 + 1 我很赞同!

查看全部评分

本帖被以下淘专辑推荐:

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

jtjt68 发表于 2025-8-7 20:20
厉害,谢谢分享原创作品
dork 发表于 2025-8-8 11:00
帮楼主转成代码模式,以方便后来人复制使用:
import tkinter as tk
from tkinter import ttk, filedialog, scrolledtext, messagebox
import os
import sys
import threading
import subprocess
import re
from datetime import datetime

class YoukuDownloader:
    def __init__(self, root):
        self.root = root
        self.root.title("优酷视频下载工具")
        self.root.geometry("800x600")
        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.style.configure("TCombobox", font=("SimHei", 10))

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

        # URL输入区域
        self.url_frame = ttk.LabelFrame(self.main_frame, text="视频URL", padding="10")
        self.url_frame.pack(fill=tk.X, pady=5)

        self.url_label = ttk.Label(self.url_frame, text="视频地址:")
        self.url_label.pack(side=tk.LEFT, padx=5)

        self.url_entry = ttk.Entry(self.url_frame)
        self.url_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        self.url_entry.insert(0, "https://v.youku.com/")

        # 输出路径选择区域
        self.path_frame = ttk.LabelFrame(self.main_frame, text="保存设置", padding="10")
        self.path_frame.pack(fill=tk.X, pady=5)

        self.path_label = ttk.Label(self.path_frame, text="保存路径:")
        self.path_label.pack(side=tk.LEFT, padx=5)

        self.path_entry = ttk.Entry(self.path_frame)
        self.path_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        self.path_entry.insert(0, os.path.expanduser("~/Downloads"))

        self.browse_btn = ttk.Button(self.path_frame, text="浏览...", command=self.browse_path)
        self.browse_btn.pack(side=tk.LEFT, padx=5)

        # 清晰度选择区域
        self.quality_frame = ttk.LabelFrame(self.main_frame, text="下载设置", padding="10")
        self.quality_frame.pack(fill=tk.X, pady=5)

        self.quality_label = ttk.Label(self.quality_frame, text="清晰度:")
        self.quality_label.pack(side=tk.LEFT, padx=5)

        self.quality_var = tk.StringVar()
        self.quality_combobox = ttk.Combobox(
            self.quality_frame,
            textvariable=self.quality_var,
            state="readonly",
            width=15
        )
        # 初始选项,后续会根据视频信息更新
        self.quality_combobox['values'] = ["自动选择", "高清", "标清", "流畅"]
        self.quality_combobox.current(0)
        self.quality_combobox.pack(side=tk.LEFT, padx=5)

        self.format_label = ttk.Label(self.quality_frame, text="输出格式:")
        self.format_label.pack(side=tk.LEFT, padx=5)

        self.format_var = tk.StringVar(value="mp4")
        self.format_combobox = ttk.Combobox(
            self.quality_frame,
            textvariable=self.format_var,
            state="readonly",
            width=10
        )
        self.format_combobox['values'] = ["mp4", "flv", "webm"]
        self.format_combobox.pack(side=tk.LEFT, padx=5)

        # 按钮区域
        self.btn_frame = ttk.Frame(self.main_frame, padding="10")
        self.btn_frame.pack(fill=tk.X, pady=5)

        self.fetch_btn = ttk.Button(self.btn_frame, text="获取视频信息", command=self.fetch_video_info)
        self.fetch_btn.pack(side=tk.LEFT, padx=5)

        self.download_btn = ttk.Button(self.btn_frame, text="开始下载", command=self.start_download)
        self.download_btn.pack(side=tk.LEFT, padx=5)

        self.cancel_btn = ttk.Button(self.btn_frame, text="取消下载", command=self.cancel_download)
        self.cancel_btn.pack(side=tk.LEFT, padx=5)
        self.cancel_btn.config(state=tk.DISABLED)

        # 日志区域
        self.log_frame = ttk.LabelFrame(self.main_frame, text="日志信息", padding="10")
        self.log_frame.pack(fill=tk.BOTH, expand=True, pady=5)

        self.log_text = scrolledtext.ScrolledText(self.log_frame, wrap=tk.WORD, font=("SimHei", 9))
        self.log_text.pack(fill=tk.BOTH, expand=True)
        self.log_text.config(state=tk.DISABLED)

        # 下载线程和进程控制
        self.download_thread = None
        self.download_process = None
        self.is_downloading = False

        # 初始化日志
        self.log("优酷视频下载工具已启动")

    def browse_path(self):
        """选择保存路径"""
        path = filedialog.askdirectory()
        if path:
            self.path_entry.delete(0, tk.END)
            self.path_entry.insert(0, path)

    def log(self, message):
        """添加日志信息"""
        self.log_text.config(state=tk.NORMAL)
        timestamp = datetime.now().strftime("%H:%M:%S")
        self.log_text.insert(tk.END, f"[{timestamp}] {message}\n")
        self.log_text.see(tk.END)  # 滚动到最新日志
        self.log_text.config(state=tk.DISABLED)

    def fetch_video_info(self):
        """获取视频信息,主要是可用的清晰度"""
        url = self.url_entry.get().strip()
        if not url:
            messagebox.showerror("错误", "请输入视频URL")
            return

        self.log("正在获取视频信息...")

        # 在新线程中执行,避免UI卡顿
        threading.Thread(target=self._do_fetch_info, args=(url,), daemon=True).start()

    def _do_fetch_info(self, url):
        """实际执行获取视频信息的操作"""
        try:
            # 使用you-get查看视频信息
            result = subprocess.run(
                ["you-get", "--info", url],
                capture_output=True,
                text=True,
                encoding="utf-8",
                errors="replace"
            )

            output = result.stdout + result.stderr
            self.log("视频信息获取成功")

            # 解析输出,提取可用的清晰度
            qualities = []
            # 简单的正则匹配,可能需要根据实际输出调整
            pattern = re.compile(r'\[.*?\] (.*?) .*?(\d+x\d+)')
            matches = pattern.findall(output)

            if matches:
                qualities = [f"{q[0]} ({q[1]})" for q in matches]
                # 在UI线程中更新下拉框
                self.root.after(0, self._update_quality_combobox, qualities)
            else:
                self.log("未识别到可用的清晰度信息,使用默认选项")

        except Exception as e:
            self.log(f"获取视频信息失败: {str(e)}")

    def _update_quality_combobox(self, qualities):
        """更新清晰度选择下拉框"""
        if qualities:
            self.quality_combobox['values'] = ["自动选择"] + qualities
            self.quality_combobox.current(0)
            self.log(f"检测到可用清晰度: {', '.join(qualities)}")

    def start_download(self):
        """开始下载视频"""
        url = self.url_entry.get().strip()
        output_path = self.path_entry.get().strip()
        quality = self.quality_var.get()
        output_format = self.format_var.get()

        if not url:
            messagebox.showerror("错误", "请输入视频URL")
            return

        if not output_path or not os.path.isdir(output_path):
            messagebox.showerror("错误", "请选择有效的保存路径")
            return

        self.is_downloading = True
        self.download_btn.config(state=tk.DISABLED)
        self.cancel_btn.config(state=tk.NORMAL)
        self.fetch_btn.config(state=tk.DISABLED)

        self.log(f"开始下载视频: {url}")
        self.log(f"保存路径: {output_path}")
        self.log(f"选择清晰度: {quality}")
        self.log(f"输出格式: {output_format}")

        # 在新线程中执行下载,避免UI卡顿
        self.download_thread = threading.Thread(
            target=self._do_download,
            args=(url, output_path, quality, output_format),
            daemon=True
        )
        self.download_thread.start()

    def _do_download(self, url, output_path, quality, output_format):
        """实际执行下载操作"""
        try:
            # 构建you-get命令
            cmd = [
                "you-get",
                "-o", output_path,
                "-O", f"video.{output_format}",  # 输出文件名
            ]

            # 如果不是自动选择,添加清晰度参数
            if quality != "自动选择":
                # 提取清晰度名称
                quality_name = quality.split()[0]
                cmd.extend(["-Q", quality_name])

            cmd.append(url)

            # 执行下载命令
            self.download_process = subprocess.Popen(
                cmd,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                text=True,
                encoding="utf-8",
                errors="replace"
            )

            # 实时输出日志
            for line in self.download_process.stdout:
                if not self.is_downloading:
                    break
                self.log(line.strip())

            # 等待进程结束
            self.download_process.wait()

            if self.is_downloading:
                if self.download_process.returncode == 0:
                    self.log("视频下载完成!")
                    self.root.after(0, lambda: messagebox.showinfo("成功", "视频下载完成!"))
                else:
                    self.log(f"下载失败,返回代码: {self.download_process.returncode}")
                    self.root.after(0, lambda: messagebox.showerror("失败", "视频下载失败!"))

        except Exception as e:
            self.log(f"下载过程中发生错误: {str(e)}")
            self.root.after(0, lambda: messagebox.showerror("错误", f"下载过程中发生错误: {str(e)}"))

        finally:
            self.is_downloading = False
            self.root.after(0, self._download_finished)

    def _download_finished(self):
        """下载完成后更新UI状态"""
        self.download_btn.config(state=tk.NORMAL)
        self.cancel_btn.config(state=tk.DISABLED)
        self.fetch_btn.config(state=tk.NORMAL)
        self.download_process = None
        self.download_thread = None

    def cancel_download(self):
        """取消下载"""
        if self.is_downloading and self.download_process:
            if messagebox.askyesno("确认", "确定要取消下载吗?"):
                self.log("正在取消下载...")
                self.is_downloading = False
                # 终止下载进程
                try:
                    self.download_process.terminate()
                    self.log("下载已取消")
                except Exception as e:
                    self.log(f"取消下载时发生错误: {str(e)}")

if __name__ == "__main__":
    # 检查是否安装了you-get
    try:
        subprocess.run(["you-get", "--version"], capture_output=True, check=True)
    except (subprocess.SubprocessError, FileNotFoundError):
        print("未检测到you-get,请先安装: pip install you-get")
        sys.exit(1)

    root = tk.Tk()
    app = YoukuDownloader(root)
    root.mainloop()


[Python] 纯文本查看 复制代码
import tkinter as tk
from tkinter import ttk, filedialog, scrolledtext, messagebox
import os
import sys
import threading
import subprocess
import re
from datetime import datetime

class YoukuDownloader:
    def __init__(self, root):
        self.root = root
        self.root.title("优酷视频下载工具")
        self.root.geometry("800x600")
        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.style.configure("TCombobox", font=("SimHei", 10))
        
        # 创建主框架
        self.main_frame = ttk.Frame(root, padding="10")
        self.main_frame.pack(fill=tk.BOTH, expand=True)
        
        # URL输入区域
        self.url_frame = ttk.LabelFrame(self.main_frame, text="视频URL", padding="10")
        self.url_frame.pack(fill=tk.X, pady=5)
        
        self.url_label = ttk.Label(self.url_frame, text="视频地址:")
        self.url_label.pack(side=tk.LEFT, padx=5)
        
        self.url_entry = ttk.Entry(self.url_frame)
        self.url_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        self.url_entry.insert(0, "https://v.youku.com/")
        
        # 输出路径选择区域
        self.path_frame = ttk.LabelFrame(self.main_frame, text="保存设置", padding="10")
        self.path_frame.pack(fill=tk.X, pady=5)
        
        self.path_label = ttk.Label(self.path_frame, text="保存路径:")
        self.path_label.pack(side=tk.LEFT, padx=5)
        
        self.path_entry = ttk.Entry(self.path_frame)
        self.path_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        self.path_entry.insert(0, os.path.expanduser("~/Downloads"))
        
        self.browse_btn = ttk.Button(self.path_frame, text="浏览...", command=self.browse_path)
        self.browse_btn.pack(side=tk.LEFT, padx=5)
        
        # 清晰度选择区域
        self.quality_frame = ttk.LabelFrame(self.main_frame, text="下载设置", padding="10")
        self.quality_frame.pack(fill=tk.X, pady=5)
        
        self.quality_label = ttk.Label(self.quality_frame, text="清晰度:")
        self.quality_label.pack(side=tk.LEFT, padx=5)
        
        self.quality_var = tk.StringVar()
        self.quality_combobox = ttk.Combobox(
            self.quality_frame,
            textvariable=self.quality_var,
            state="readonly",
            width=15
        )
        # 初始选项,后续会根据视频信息更新
        self.quality_combobox['values'] = ["自动选择", "高清", "标清", "流畅"]
        self.quality_combobox.current(0)
        self.quality_combobox.pack(side=tk.LEFT, padx=5)
        
        self.format_label = ttk.Label(self.quality_frame, text="输出格式:")
        self.format_label.pack(side=tk.LEFT, padx=5)
        
        self.format_var = tk.StringVar(value="mp4")
        self.format_combobox = ttk.Combobox(
            self.quality_frame,
            textvariable=self.format_var,
            state="readonly",
            width=10
        )
        self.format_combobox['values'] = ["mp4", "flv", "webm"]
        self.format_combobox.pack(side=tk.LEFT, padx=5)
        
        # 按钮区域
        self.btn_frame = ttk.Frame(self.main_frame, padding="10")
        self.btn_frame.pack(fill=tk.X, pady=5)
        
        self.fetch_btn = ttk.Button(self.btn_frame, text="获取视频信息", command=self.fetch_video_info)
        self.fetch_btn.pack(side=tk.LEFT, padx=5)
        
        self.download_btn = ttk.Button(self.btn_frame, text="开始下载", command=self.start_download)
        self.download_btn.pack(side=tk.LEFT, padx=5)
        
        self.cancel_btn = ttk.Button(self.btn_frame, text="取消下载", command=self.cancel_download)
        self.cancel_btn.pack(side=tk.LEFT, padx=5)
        self.cancel_btn.config(state=tk.DISABLED)
        
        # 日志区域
        self.log_frame = ttk.LabelFrame(self.main_frame, text="日志信息", padding="10")
        self.log_frame.pack(fill=tk.BOTH, expand=True, pady=5)
        
        self.log_text = scrolledtext.ScrolledText(self.log_frame, wrap=tk.WORD, font=("SimHei", 9))
        self.log_text.pack(fill=tk.BOTH, expand=True)
        self.log_text.config(state=tk.DISABLED)
        
        # 下载线程和进程控制
        self.download_thread = None
        self.download_process = None
        self.is_downloading = False
        
        # 初始化日志
        self.log("优酷视频下载工具已启动")
        
    def browse_path(self):
        """选择保存路径"""
        path = filedialog.askdirectory()
        if path:
            self.path_entry.delete(0, tk.END)
            self.path_entry.insert(0, path)
   
    def log(self, message):
        """添加日志信息"""
        self.log_text.config(state=tk.NORMAL)
        timestamp = datetime.now().strftime("%H:%M:%S")
        self.log_text.insert(tk.END, f"[{timestamp}] {message}\n")
        self.log_text.see(tk.END)  # 滚动到最新日志
        self.log_text.config(state=tk.DISABLED)
   
    def fetch_video_info(self):
        """获取视频信息,主要是可用的清晰度"""
        url = self.url_entry.get().strip()
        if not url:
            messagebox.showerror("错误", "请输入视频URL")
            return
        
        self.log("正在获取视频信息...")
        
        # 在新线程中执行,避免UI卡顿
        threading.Thread(target=self._do_fetch_info, args=(url,), daemon=True).start()
   
    def _do_fetch_info(self, url):
        """实际执行获取视频信息的操作"""
        try:
            # 使用you-get查看视频信息
            result = subprocess.run(
                ["you-get", "--info", url],
                capture_output=True,
                text=True,
                encoding="utf-8",
                errors="replace"
            )
            
            output = result.stdout + result.stderr
            self.log("视频信息获取成功")
            
            # 解析输出,提取可用的清晰度
            qualities = []
            # 简单的正则匹配,可能需要根据实际输出调整
            pattern = re.compile(r'\[.*?\] (.*?) .*?(\d+x\d+)')
            matches = pattern.findall(output)
            
            if matches:
                qualities = [f"{q[0]} ({q[1]})" for q in matches]
                # 在UI线程中更新下拉框
                self.root.after(0, self._update_quality_combobox, qualities)
            else:
                self.log("未识别到可用的清晰度信息,使用默认选项")
               
        except Exception as e:
            self.log(f"获取视频信息失败: {str(e)}")
   
    def _update_quality_combobox(self, qualities):
        """更新清晰度选择下拉框"""
        if qualities:
            self.quality_combobox['values'] = ["自动选择"] + qualities
            self.quality_combobox.current(0)
            self.log(f"检测到可用清晰度: {', '.join(qualities)}")
   
    def start_download(self):
        """开始下载视频"""
        url = self.url_entry.get().strip()
        output_path = self.path_entry.get().strip()
        quality = self.quality_var.get()
        output_format = self.format_var.get()
        
        if not url:
            messagebox.showerror("错误", "请输入视频URL")
            return
        
        if not output_path or not os.path.isdir(output_path):
            messagebox.showerror("错误", "请选择有效的保存路径")
            return
        
        self.is_downloading = True
        self.download_btn.config(state=tk.DISABLED)
        self.cancel_btn.config(state=tk.NORMAL)
        self.fetch_btn.config(state=tk.DISABLED)
        
        self.log(f"开始下载视频: {url}")
        self.log(f"保存路径: {output_path}")
        self.log(f"选择清晰度: {quality}")
        self.log(f"输出格式: {output_format}")
        
        # 在新线程中执行下载,避免UI卡顿
        self.download_thread = threading.Thread(
            target=self._do_download,
            args=(url, output_path, quality, output_format),
            daemon=True
        )
        self.download_thread.start()
   
    def _do_download(self, url, output_path, quality, output_format):
        """实际执行下载操作"""
        try:
            # 构建you-get命令
            cmd = [
                "you-get",
                "-o", output_path,
                "-O", f"video.{output_format}",  # 输出文件名
            ]
            
            # 如果不是自动选择,添加清晰度参数
            if quality != "自动选择":
                # 提取清晰度名称
                quality_name = quality.split()[0]
                cmd.extend(["-Q", quality_name])
               
            cmd.append(url)
            
            # 执行下载命令
            self.download_process = subprocess.Popen(
                cmd,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                text=True,
                encoding="utf-8",
                errors="replace"
            )
            
            # 实时输出日志
            for line in self.download_process.stdout:
                if not self.is_downloading:
                    break
                self.log(line.strip())
            
            # 等待进程结束
            self.download_process.wait()
            
            if self.is_downloading:
                if self.download_process.returncode == 0:
                    self.log("视频下载完成!")
                    self.root.after(0, lambda: messagebox.showinfo("成功", "视频下载完成!"))
                else:
                    self.log(f"下载失败,返回代码: {self.download_process.returncode}")
                    self.root.after(0, lambda: messagebox.showerror("失败", "视频下载失败!"))
        
        except Exception as e:
            self.log(f"下载过程中发生错误: {str(e)}")
            self.root.after(0, lambda: messagebox.showerror("错误", f"下载过程中发生错误: {str(e)}"))
        
        finally:
            self.is_downloading = False
            self.root.after(0, self._download_finished)
   
    def _download_finished(self):
        """下载完成后更新UI状态"""
        self.download_btn.config(state=tk.NORMAL)
        self.cancel_btn.config(state=tk.DISABLED)
        self.fetch_btn.config(state=tk.NORMAL)
        self.download_process = None
        self.download_thread = None
   
    def cancel_download(self):
        """取消下载"""
        if self.is_downloading and self.download_process:
            if messagebox.askyesno("确认", "确定要取消下载吗?"):
                self.log("正在取消下载...")
                self.is_downloading = False
                # 终止下载进程
                try:
                    self.download_process.terminate()
                    self.log("下载已取消")
                except Exception as e:
                    self.log(f"取消下载时发生错误: {str(e)}")

if __name__ == "__main__":
    # 检查是否安装了you-get
    try:
        subprocess.run(["you-get", "--version"], capture_output=True, check=True)
    except (subprocess.SubprocessError, FileNotFoundError):
        print("未检测到you-get,请先安装: pip install you-get")
        sys.exit(1)
   
    root = tk.Tk()
    app = YoukuDownloader(root)
    root.mainloop()
lxhwan100 发表于 2025-8-7 20:34
zpwz 发表于 2025-8-7 20:45
后生真牛!
shsww 发表于 2025-8-7 20:46
会编程真好啊
xiaoshuimian 发表于 2025-8-7 20:56
能下VIP和点播的视频吗
hrh123 发表于 2025-8-7 21:02
【公告】发帖代码插入以及添加链接教程(有福利)
https://www.52pojie.cn/thread-713042-1-1.html
(出处: 吾爱破解论坛)
010xml 发表于 2025-8-7 21:30
你是初二学生?厉害,感觉就像小学生会英语四六级一样
超逸绝尘 发表于 2025-8-7 21:52
我来看看,确实不错
rockliuxn 发表于 2025-8-7 22:08
支持,继续加油!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2026-9-16 00:00

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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