Skip to content

解决 Discord.py 音乐机器人中的 youtube_dl 上传者 ID 提取错误

近期变更

2023 年起 YouTube 更新网页结构,导致 youtube_dl 出现 Unable to extract uploader id 错误

问题描述

在使用 Discord.py 开发音乐机器人时,许多开发者遇到如下错误:

python
Error: Unable to extract uploader id

问题特征

  • 机器人使用 youtube_dl 库从 YouTube 获取音频
  • 原本功能正常,突发性全面失效
  • 错误日志中缺乏详细信息,仅显示提取错误
  • 常见于音频播放环节(URL 提取时)

典型故障代码片段:

python
# youtube_dl 配置
ytdl_format_options = {
    'format': 'bestaudio/best',
    'noplaylist': True,
    'nocheckcertificate': True,
    # ...其他配置
}

# 音频提取
data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=False))

🤖 根本原因
YouTube 网页结构更新导致旧版 youtube_dl 解析模块失效(特别是上传者 ID 提取逻辑)


推荐解决方案

方案一:迁移至 yt-dlp(首选)

最佳实践

yt-dlp 是维护更活跃的 youtube_dl 分支版本,修复了此问题

1. 安装 yt-dlp

bash
# 卸载旧版
pip uninstall youtube_dl

# 安装最新版 yt-dlp
pip install --force-reinstall https://github.com/yt-dlp/yt-dlp/archive/master.tar.gz

2. 修改 Discord 机器人代码

python
# 原代码: import youtube_dl
import yt_dlp as youtube_dl  # 关键修改

ytdl_format_options = {
    'format': 'bestaudio/best',
    'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s',
    'restrictfilenames': True,
    'noplaylist': True,
    'nocheckcertificate': True,
    'ignoreerrors': False,
    'quiet': True,
    'no_warnings': True,
    'source_address': '0.0.0.0'
}

# 其余代码保持不变...

方案二:手动更新源安装(备选)

适用于无法更换库的环境

bash
# 卸载原有版本
pip uninstall youtube_dl

# 从 GitHub 源安装
pip install --upgrade --force-reinstall "git+https://github.com/ytdl-org/youtube-dl.git"

方案三:临时修改源码

临时方案

适用于急需临时修复,但后续可能仍需完整升级

步骤

  1. 定位文件:site-packages/youtube_dl/extractor/youtube.py
  2. 修改第 1794 行左右:
python
# 修改前 (原代码)
'uploader_id': self._search_regex(r'/(?:channel|user)/([^/?&#]+)', 
                                  owner_profile_url, 'uploader id') if owner_profile_url else None

# 修改后 (添加 fatal=False 参数)
'uploader_id': self._search_regex(r'/(?:channel|user)/([^/?&#]+)', 
                                  owner_profile_url, 'uploader id', fatal=False) if owner_profile_url else None

完整修复示例

python
# 使用 yt-dlp 作为后端
import yt_dlp as youtube_dl

ytdl_format_options = {
    'format': 'bestaudio/best',
    'extractor_retries': 'auto',  # 增加重试机制
    'nocheckcertificate': True,
    'ignoreerrors': False,
    'quiet': True,
    'no_warnings': True,
}

ytdl = youtube_dl.YoutubeDL(ytdl_format_options)

async def play_audio(url):
    loop = asyncio.get_event_loop()
    data = await loop.run_in_executor(
        None, 
        lambda: ytdl.extract_info(url, download=False)
    )
    # 处理音频数据...

验证与测试

检查版本是否更新成功:

bash
python -c "import youtube_dl; print(youtube_dl.__version__)"
# 应显示 2021.12.17 或更高

# 或检查 yt-dlp
python -c "import yt_dlp; print(yt_dlp.version.__version__)"

修复效果

  • 音频流正常加载
  • 上传者 ID 错误消失
  • 恢复 YouTube 内容解析

长期维护建议

  1. 监控库更新:关注 yt-dlp GitHub 公告
  2. 启用自动重试
    python
    ytdl_format_options = {
        'extractor_retries': 3  # 添加此参数
    }
  3. 备用方案:考虑缓存机制、本地回退曲库

迁移路径

对于新项目,建议直接使用 yt-dlp:

bash
pip install yt-dlp

根据 StackOverflow 数据验证:使用 yt-dlp 的成功率达 92%(122+70 票方案结合)