如何用pytube检查已下载文件,仅下载播放列表中的缺失文件?
修改后的pytube播放列表下载函数(支持覆盖/跳过缺失文件)
核心改动说明
- 移除文件夹存在时的直接报错逻辑,改为询问用户选择操作模式:1=覆盖所有文件,2=仅下载本地缺失的文件
- 预加载视频对象并获取标题,用于精准匹配本地已生成的MP3文件
- 修复原函数中的变量拼写错误(
playlsit_name→playlist_name) - 优化下载计数逻辑,避免重复遍历文件夹计数
- 新增本地文件检查逻辑,仅在需要时执行下载、转码和元数据写入操作
- 增加异常捕获,单个视频处理失败不会中断整个播放列表的下载
完整修改代码
import os from pathlib import Path from pytube import Playlist, YouTube from moviepy.editor import AudioFileClip import eyed3 import re # 假设以下变量为外部定义(根据实际场景调整) # get_link = "你的YouTube播放列表URL" # user_path = "本地存储根路径" # var1 = 1 # 控制是否写入音频元数据(1=开启,0=关闭) def download_playlist(): # 获取播放列表对象 playlist = Playlist(get_link) playlist_name = playlist.title # 修复原拼写错误:playlsit_name → playlist_name main_dir = os.path.join(user_path, playlist_name) # 跨平台路径拼接 # 处理文件夹已存在的情况 if os.path.exists(main_dir): print(f"播放列表文件夹「{playlist_name}」已存在,请选择操作:") print("1. 覆盖所有已下载文件") print("2. 仅下载本地缺失的文件") # 循环获取有效输入 while True: choice = input("请输入选择(1/2):") if choice in ["1", "2"]: break print("输入无效,请重新输入1或2") download_mode = choice else: os.mkdir(main_dir, mode=0o666) download_mode = "1" # 新文件夹默认下载所有视频 # 预加载视频对象,减少重复请求 videos = playlist.videos videos_num = len(videos) completed_count = 0 # 已完成处理的视频计数 for video in videos: # 处理视频标题中的非法文件名字符 safe_title = re.sub(r'[\\/*?:"<>|]', "", video.title) target_mp3_path = os.path.join(main_dir, f"{safe_title}.mp3") # 跳过模式:检测到已存在则跳过 if download_mode == "2" and os.path.exists(target_mp3_path): print(f"已存在:{safe_title}.mp3,跳过下载") completed_count += 1 print(f"进度:{completed_count}/{videos_num}") continue # 执行下载、转码、元数据写入流程 try: print(f"正在处理:{video.title}") # 下载音频流 temp_mp4_path = video.streams.filter(only_audio=True).first().download(main_dir) # 转码为MP3 audio_clip = AudioFileClip(temp_mp4_path) audio_clip.write_audiofile(target_mp3_path) # 删除临时MP4文件 os.remove(temp_mp4_path) # 写入音频元数据(如果开启) if var1 == 1: audio_file = eyed3.load(target_mp3_path) if not audio_file.tag: audio_file.initTag() # 处理频道名称(去除-Topic后缀) channel_name = video.author if " - Topic" in channel_name: channel_name = channel_name.replace(" - Topic", "") audio_file.tag.artist = channel_name audio_file.tag.title = video.title audio_file.tag.save() completed_count += 1 print(f"进度:{completed_count}/{videos_num}") except Exception as e: print(f"处理视频「{video.title}」时出错:{str(e)}") continue print("下载完成!!!")
关键细节说明
- 使用
playlist.videos预加载所有视频对象,减少重复向YouTube发起HTTP请求,提升整体效率 - 对视频标题进行非法字符过滤,避免生成操作系统无法识别的文件名
- 采用
os.path.join替代硬编码的路径拼接,确保代码在Windows、Linux、macOS等平台都能正常运行 - 增加异常捕获逻辑,单个视频处理失败不会导致整个播放列表下载中断
内容的提问来源于stack exchange,提问作者Shoter3000
相关产品推荐
相关产品推荐

