Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DownSub 爬虫 — YouTube 字幕下载工具

通过逆向 DownSub.com 前端 API,实现的 YouTube 字幕下载命令行工具。

功能特性

  • 单视频下载 — 下载任意 YouTube 视频的字幕
  • 播放列表下载 — 一键下载整个播放列表的字幕(支持 100+ 视频)
  • 多格式支持 — SRT / VTT / TXT 三种字幕格式
  • 多语言 — 支持所有 YouTube 提供的字幕语言
  • 自动翻译字幕 — 下载 YouTube 自动生成的字幕
  • 双语字幕 — 同时下载两种语言
  • 失败重试 — 自动重试临时错误(503/429),失败记录可单独重试
  • 备选下载源 — DownSub 失败时自动切换到 yt-dlp 直下字幕
  • SSL 代理兼容 — 支持 Clash 等代理环境

工作原理

用户输入 YouTube URL
       ↓
解析 URL → 提取 videoId / playlistId
       ↓
AES-256-CBC 加密 ID(兼容 DownSub 前端加密)
       ↓
调用 DownSub API → 获取字幕列表
       ↓
构建下载 URL → 下载字幕文件

核心是通过逆向 DownSub 前端的 JavaScript 代码,复现了其 AES 加密流程和 API 调用逻辑,不依赖浏览器,也不依赖 DownSub 网站本身。

安装

环境要求

  • Python 3.10+
  • pip

安装步骤

# 1. 安装依赖
pip install -r downsub_crawler/requirements.txt

# 2. 验证安装
python -m downsub_crawler --help

可选依赖

yt-dlp — 用于两个场景:

  • 播放列表枚举:获取超过 50 个视频的大播放列表(DownSub API 分页有 Bug)
  • 备选字幕下载:当 DownSub 下载失败时自动切换
pip install yt-dlp
# yt-dlp 不是必须的,未安装时自动回退到 DownSub API

快速开始

下载单个视频的字幕

python -m downsub_crawler "https://www.youtube.com/watch?v=dQw4w9WgXcQ"

默认下载所有语言,保存到当前目录的 .srt 文件。

下载播放列表全部字幕

python -m downsub_crawler \
  "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" \
  --lang en --format txt -o ./subtitles

详细用法

参数说明

参数 简写 说明
url YouTube 视频/播放列表 URL(--retry-failed 模式下可选)
--lang -l 字幕语言代码,如 enzhja(默认全部)
--output -o 输出目录(默认当前目录)
--format -f 字幕格式:srtvtttxt(默认 srt
--list-langs 仅列出可用语言,不下载
--bilingual 下载双语字幕
--playlist -p 强制以播放列表模式下载
--max-videos -m 最多下载前 N 个视频(0=全部)
--retry-failed 读取 retry_failed.json 重试失败视频
--ytdlp-cookies cookies.txt 文件路径(用于 yt-dlp 绕过 YouTube bot 检测)
--ytdlp-cookies-browser 从浏览器读取 cookies,如 chromeedgebrave
--verbose -v 显示详细日志
--verbose -v 显示详细日志
--debug 显示调试日志

使用示例

指定语言和格式:

python -m downsub_crawler "https://youtu.be/dQw4w9WgXcQ" --lang zh --format vtt

指定输出目录:

python -m downsub_crawler "https://youtu.be/dQw4w9WgXcQ" --lang en -o ./subtitles

列出可用语言(不下载):

python -m downsub_crawler "https://youtu.be/dQw4w9WgXcQ" --list-langs

下载播放列表前 10 个视频:

python -m downsub_crawler \
  "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" \
  --lang en --format txt --max-videos 10 -o ./subtitles

下载双语字幕(英文 + 中文):

python -m downsub_crawler "https://youtu.be/dQw4w9WgXcQ" --bilingual

使用 cookies 绕过 bot 检测:

# 方式 A:使用 cookies.txt 文件
python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en --ytdlp-cookies ./cookies.txt

# 方式 B:直接从 Chrome 读取 cookies
python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en --ytdlp-cookies-browser chrome

高级功能

SSL 代理问题

如果你的环境通过代理(如 Clash)上网,Python 的 requests 库可能遇到 SSL 错误。

# 方案 1:使用 curl 替代 requests(推荐)
DOWNSUB_USE_CURL=1 python -m downsub_crawler "https://youtu.be/dQw4w9WgXcQ"

# 方案 2:自动回退(不设置环境变量,requests 失败会自动切 curl)
python -m downsub_crawler "https://youtu.be/dQw4w9WgXcQ"

失败重试机制

下载播放列表时,临时失败(503/SSL 错误)的视频会自动记录:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  总计: 110  |  ✓ 88  |  ✗ 22  |  耗时 33:12
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ 22 个视频下载失败
   失败记录已保存: subtitles/retry_failed.json
   重试命令:
     python -m downsub_crawler --retry-failed subtitles/retry_failed.json --lang en --format txt -o subtitles

使用 --retry-failed 重试失败视频:

# 单独重试失败的视频(不重新下载已成功的)
python -m downsub_crawler --retry-failed ./subtitles/retry_failed.json --lang en --format txt -o ./subtitles

retry_failed.json 文件格式:

[
  {
    "url": "https://www.youtube.com/watch?v=1GI2uB5CpnE",
    "title": "Video Title",
    "reason": "503 Server Error",
    "index": 4,
    "timestamp": "2026-06-07T12:34:56"
  }
]

yt-dlp 备选下载

当 DownSub API 下载失败时(如 503 错误),程序会自动尝试用 yt-dlp 直接从 YouTube 下载字幕。

# 确保 yt-dlp 已安装
pip install yt-dlp

# 正常运行即可,备选下载会在 DownSub 失败时自动触发
DOWNSUB_USE_CURL=1 python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en

注意: YouTube 可能对程序化访问有 bot 检测,导致备选下载失败。解决方法见下方的 yt-dlp Cookies 配置指南


yt-dlp Cookies 配置指南

当 yt-dlp 报 "Sign in to confirm you're not a bot" 错误时,需要提供浏览器 cookies 来证明你是人类用户。

方式一:Chrome 扩展导出 cookies.txt(推荐,最通用)

步骤 1:安装 cookies 导出扩展

在 Chrome 浏览器中安装以下任一扩展:

步骤 2:登录 YouTube

在 Chrome 中访问 youtube.com 并登录你的 Google 账号(如果有的话)。

步骤 3:导出 cookies

点击扩展图标 → 选择 Export → 将文件保存为 cookies.txt

⚠️ 确保只导出了 youtube.com 的 cookies。一些扩展允许按域名筛选。

步骤 4:将 cookies.txt 放到 WSL 中

Windows 的 Chrome 下载目录通常可以通过 WSL 访问:

# 方法 A:直接从 Windows 下载目录复制
cp /mnt/c/Users/btroops/Downloads/cookies.txt ~/coding/cookies.txt

# 方法 B:直接放到项目目录
# 在 Windows 文件管理器中,将 cookies.txt 复制到 \\wsl.localhost\Ubuntu\home\btroops\coding\

步骤 5:使用 cookies 运行爬虫

python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en --ytdlp-cookies ~/coding/cookies.txt

如果一切正常,yt-dlp 备选下载就能绕过 bot 检测,成功下载字幕。

步骤 6(可选):验证 cookies 是否生效

yt-dlp --cookies ~/coding/cookies.txt --write-sub --sub-lang en --skip-download \
  --convert-subs srt --print after_move:filepath "https://www.youtube.com/watch?v=1GI2uB5CpnE"

没有 "Sign in to confirm" 错误即为成功。

⚠️ 安全提示: cookies.txt 包含你的登录凭证,不要分享给他人,用完可删除。 ⚠️ 有效期: YouTube cookies 大约 6-12 个月有效,过期后重新导出一份即可。


方式二:从浏览器直接读取(--cookies-from-browser)

如果你在 WSL 中安装了 Chrome/Edge,yt-dlp 可以直接读取浏览器的 cookies:

# 从 Chrome 读取
python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en --ytdlp-cookies-browser chrome

# 从 Edge 读取
python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en --ytdlp-cookies-browser edge

# 从 Brave 读取
python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en --ytdlp-cookies-browser brave

注意: 在 WSL 中,这只对安装在 Linux 端的浏览器有效。Windows 端的 Chrome 无法直接被 WSL 读取。


方式三:手动创建 cookies.txt(高级)

如果扩展导出不方便,可以手动创建一个包含最少必要 cookies 的 cookies.txt 文件。

格式为 Netscape cookie 格式

# Netscape HTTP Cookie File
.youtube.com	TRUE	/	TRUE	0	CONSENT	YES+shp.gws-20250606+1

最少需要的字段:CONSENT cookie(用于绕过 YouTube 的年龄/地区确认)。

从浏览器开发者工具中获取:

  1. 打开 YouTube,按 F12 打开 DevTools
  2. 进入 ApplicationStorageCookieshttps://www.youtube.com
  3. 找到 CONSENT__Secure-3PSID 等关键 cookie
  4. 按 Netscape 格式写入 cookies.txt

方式四:Windows 端 Chrome 自动读取(通过 WSL 脚本)

如果 Chrome 安装在 Windows 端,可以用以下方法让 WSL 中的 yt-dlp 读取它:

# 安装 WSL 的 chrome 读取工具
sudo apt install python3-pip
pip install browsercookie

# 或者使用 yt-dlp 的 Windows 路径映射
# 启动 yt-dlp 时指定 Windows Chrome 的 cookie 路径
yt-dlp --cookies "/mnt/c/Users/btroops/AppData/Local/Google/Chrome/User Data/Default/Cookies" ...

但这种方式需要解密 Chrome 的加密 cookie 存储,比较复杂。推荐使用方式一(扩展导出)。


常见问题

Q: 导出的 cookies.txt 不起作用?

  • 确保导出前已登录 YouTube
  • 确保 cookies.txt 是 Netscape 格式(扩展导出默认就是)
  • 检查文件路径是否正确:--ytdlp-cookies $(pwd)/cookies.txt

Q: 使用 cookies 后仍然被检测?

  • YouTube 有时会对新 IP 进行额外验证
  • 尝试使用 --ytdlp-cookies-browser chrome 方式
  • 如果都不行,可能是代理 IP 被 YouTube 标记,尝试关闭代理

Q: cookies 会不会泄露?

  • cookies.txt 包含你的登录凭证,用完即删
  • 不要提交到 Git:
# 添加到 .gitignore
echo "cookies.txt" >> .gitignore

播放列表自动检测

当 URL 中包含 list= 参数时,自动以播放列表模式运行:

# 以下两条命令等效
python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en
python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --playlist --lang en

如果 URL 中含有 list= 但只想下载当前视频,可以手动指定 --max-videos 1

输出结构

目录结构

subtitles/
├── retry_failed.json                   # 失败记录(仅失败时生成)
├── 播放列表标题/                        # 播放列表模式
│   ├── 01_视频标题_en.txt
│   ├── 02_视频标题_en.txt
│   └── ...
└── (单视频模式直接输出到根目录)

文件命名规则

{序号}_{视频标题}_{语言代码}.{格式}
  │        │            │        │
  ├─ 序号(播放列表模式才有,如 01_、02_)
  ├─ 视频标题(安全文件名,最长 100 字符)
  ├─ 语言代码(如 en、zh,重复时自动加 _auto/_orig)
  └─ 文件扩展名(srt/vtt/txt)

如果同一视频同时有原始字幕和自动翻译字幕(相同语言代码),文件名会自动区分:

  • 视频标题_en.txt — 原始字幕
  • 视频标题_en_auto.txt — 自动翻译字幕
  • 视频标题_en_orig.txt — 如果 en 出现三次以上

常见问题

1. SSLEOFError / SSL 代理问题

现象: requests 报 SSL 错误,程序自动重试后失败。

解决:

DOWNSUB_USE_CURL=1 python -m downsub_crawler "https://www.youtube.com/watch?v=dQw4w9WgXcQ"

设置环境变量后使用 curl 命令行发送请求,绕过 Python 的 SSL 问题。

2. HTTP 503 Service Unavailable

现象: 下载过程中出现 503 Server Error

原因: DownSub 后端依赖 YouTube API,有频率限制。

解决:

  • 程序会自动重试 5 次(指数退避,从 1s 到 16s)
  • 大部分 503 重试后可恢复
  • 如果始终失败,使用 --retry-failed 稍后重试

3. HTTP 429 Too Many Requests

现象: 429 Too Many Requests

原因: DownSub API 限流。

解决:

  • 程序会自动重试(从 3s 开始指数退避)
  • 播放列表模式下视频间有 3~5 秒延迟,降低触发概率

4. 播放列表只能下载 50 个视频

现象: 返回 "播放列表共 50 个视频",但 YouTube 上实际有更多。

原因: DownSub 后端分页 API 已损坏,翻页返回 500。

解决: 安装 yt-dlp:

pip install yt-dlp

安装后自动切换到 yt-dlp 枚举播放列表,不受数量限制。

5. yt-dlp 报 "Sign in to confirm you're not a bot"

原因: YouTube 对程序化访问有 bot 检测,yt-dlp 需要浏览器 cookies 来通过验证。

解决: 配置 yt-dlp cookies,详见上方的 yt-dlp Cookies 配置指南

# 快速方案:用 --ytdlp-cookies-browser 直接从 Chrome 读取
python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en --ytdlp-cookies-browser chrome

# 推荐方案:用 cookies.txt 文件
python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en --ytdlp-cookies ./cookies.txt

即使不配置 cookies,程序也不会阻塞——备选下载失败时会自动记录到 retry_failed.json,不影响主流程。

6. 自动翻译字幕下载失败

现象: 只有自动翻译字幕无法下载。

原因: DownSub 的自动翻译功能需要 Premium 会员。

解决: 指定原始字幕语言 --lang en,不下载自动翻译。

技术实现

模块架构

downsub_crawler/
├── __init__.py          # 包入口
├── __main__.py          # python -m 入口
├── cli.py               # 命令行参数解析
├── crypto.py            # AES-256-CBC 加密(兼容 CryptoJS)
├── parser.py            # YouTube URL 解析
├── api.py               # DownSub API 客户端
├── downloader.py        # 字幕下载协调器
└── requirements.txt     # 依赖列表

数据流

CLI 参数
  ↓
downloader.download_playlist() / download()
  ↓
parser.process_url() → 提取 videoId, playlistId
  ↓
crypto.encrypt() → AES 加密 videoId
  ↓
api.get_video_info() → GET get-info.downsub.com/{id} → 字幕列表
  ↓
api.build_subtitle_download_url() → 构建下载 URL
  ↓
api.download_subtitle_file() → HTTP GET → 保存文件
  ↓
(失败时)api.download_subtitle_via_ytdlp() → yt-dlp 备选
  ↓
downloader._save_failed_json() → 记录失败到 retry_failed.json

API 端点

端点 方法 用途
get-info.downsub.com/{encrypted_id} GET 视频信息 + 字幕列表
get.downsub.com/?type=playlist GET 播放列表
subtitle.downsub.com/{type}/{url}/ GET 下载字幕文件
get.downsub.com/ POST 非 YouTube 源(未实现)

加密机制

  • 算法: AES-256-CBC
  • 密钥: zthxw34cdp6wfyxmpad38v52t3hsz6c5
  • 密钥派生: OpenSSL EVP_BytesToKey(基于 MD5),非 PBKDF2
  • 序列化格式: {ct: base64(ciphertext), iv: hex(iv), s: hex(salt)} → JSON → Base64URL

依赖

pycryptodome>=3.0   # AES 加密
requests>=2.28      # HTTP 客户端
yt-dlp>=2024.0      # 可选:播放列表枚举 + 备选下载

相关文档

  • 踩坑记录 — 开发过程中遇到的问题和解决方案

About

A command-line YouTube subtitle download tool built by reverse-engineering the frontend APIs of [DownSub.com](https://downsub.com).

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages