用Golang顺手撸了个在线视频Club365中文字幕下载器,真香
- 单站
- 2026-07-16 19:03:06
- 33
说真的,在线视频Club365中文字幕这玩意儿,我之前一直是用浏览器手动扒的,每次打开页面,右键检查元素,找m3u8地址,再拿个第三方工具下载字幕……折腾来折腾去,烦得要死,后来一想,干嘛不自己写个Golang脚本自动化掉?反正Golang处理网络请求和并发,那叫一个顺手。
为什么非要用Golang搞这件事?
你可能觉得,扒字幕嘛,Python不香吗?确实香,但Golang有几个点让我这个日常写后端的人觉得更舒服:
- 部署方便:编译出来一个二进制文件,扔服务器上就能跑,不用装Python环境,不用管pip依赖版本冲突。
- 并发天然:Club365这种网站,一集视频可能对应多个字幕轨道,中文字幕、英文、繁体……用Goroutine并发下载,速度拉满。
- 标准库够用:
net/http配合io包,直接搞定HTTP请求和文件写入,不用装第三方库。
我承认有时候Python的requests库写起来更短,但Golang那种“写完就能忘,永远不用回来修依赖”的感觉,太对味儿了。
第一步:摸清Club365的字幕结构
所有技术活儿,第一步都是抓包,打开Chrome开发者工具,选Network面板,然后播放一集Club365的视频,你会发现,视频流是m3u8格式的,但字幕通常不是嵌在视频里的,而是单独的 VTT 或者 SRT 文件。
具体怎么找?在Network里搜 subtitle、caption、zh 这几个关键词,大概率能找到一个JSON或XML文件,里面列出了所有可用的字幕轨道。
// 伪代码示意
type SubtitleTrack struct {
Language string `json:"language"` // "zh-CN"
URL string `json:"url"` // "https://cdn.club365.example.com/sub/xxx.vtt"
}
这个请求通常需要带个 Referer 头,否则服务器会返回403,Golang里加Header很简单:
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Referer", "https://www.club365.com/")
req.Header.Set("User-Agent", "Mozilla/5.0")
核心代码:下载并转换中文字幕
拿到VTT文件后,一步是下载,一步是转换,VTT是WebVTT格式,长得跟SRT差不多,但头部多了一行 WEBVTT,时间戳格式也略有不同,我想把它转成SRT,因为大部分播放器都原生支持SRT。
VTT原始内容长这样:
WEBVTT
Kind: captions
Language: zh-CN
00:00:01.500 --> 00:00:04.000
大家好,欢迎收看Club365
00:00:04.500 --> 00:00:08.000
今天我们来聊聊Golang并发
SRT应该长这样:
1
00:00:01,500 --> 00:00:04,000
大家好,欢迎收看Club365
2
00:00:04,500 --> 00:00:08,000
今天我们来聊聊Golang并发
转换逻辑其实就两个替换:把 换成 ,加上序号,用strings包搞一下:
func VTTtoSRT(vttData string) string {
lines := strings.Split(vttData, "\n")
var srtLines []string
seq := 1
for _, line := range lines {
if strings.Contains(line, "WEBVTT") || strings.Contains(line, "Kind:") || strings.Contains(line, "Language:") {
continue
}
if strings.Contains(line, "-->") {
line = strings.ReplaceAll(line, ".", ",")
srtLines = append(srtLines, strconv.Itoa(seq))
seq++
}
srtLines = append(srtLines, line)
}
return strings.Join(srtLines, "\n")
}
这段代码我没做太多健壮性处理,比如有的VTT可能包含注释或者空行,但够用,写工具代码嘛,先解决80%的问题,剩下的跑几次遇到bug再修。
并发出奇迹:一次性拉完所有剧集
Club365如果一个系列有30集,一集一个VTT文件,串行下载要等半天,用Goroutine搞并发,瞬间起飞:
func downloadAllSubtitles(episodes []string) {
ch := make(chan string, len(episodes))
for _, ep := range episodes {
go func(epURL string) {
data := downloadVTT(epURL)
srt := VTTtoSRT(data)
saveToFile(ep, srt)
ch <- fmt.Sprintf("✅ 完成: %s", ep)
}(ep)
}
for i := 0; i < len(episodes); i++ {
fmt.Println(<-ch)
}
}
跑起来之后,命令行里刷刷刷往外蹦绿勾,那种成就感……比手动扒字幕爽多了。
表格一把:对比手动扒 vs 脚本扒
| 对比项 | 手动扒(浏览器) | Golang脚本 |
|---|---|---|
| 时间成本 | 每集2-3分钟,30集1.5小时 | 30集30秒 |
| 出错率 | 容易复制错时间戳 | 稳定解析 |
| 多语言支持 | 需要手工切换 | 自动携带中文、英文、繁体 |
| 能否后台跑 | 不能 | 可以放服务器定时执行 |
一些坑和反思
- Cookie问题:Club365有些字幕接口需要登录态,我的解决方式是先用浏览器手动登录,导出Cookie为Netscape格式,然后用Golang的
cookiejar加载,这办法很土,但好用。 - 编码问题:有些中文字幕用的是GBK编码,Golang默认UTF-8,需要用
golang.org/x/text/encoding/simplifiedchinese这个包转码,我一开始没注意,下载下来的字幕全是乱码,查了半小时才发现。 - 文件名规范:保存字幕时,最好跟视频文件名对应上,
S01E01.zh.srt,不然以后手动挂载字幕,还得一个个重命名。
说实话,写这个脚本的初衷真的只是懒,但写着写着就发现,Golang这种“编译完往那一丢”的特性,特别适合写这种小工具——不会像Python脚本那样,隔半年想用发现依赖全挂了。
再提一嘴在线视频Club365中文字幕
如果你是追剧党,而且恰好喜欢Club365上的某些内容,但又不想被网站那层播放器绑死,这种本地字幕下载+任意播放器播放的体验,真的自由,我以前是视频会员、字幕包月全都买,后来发现很多高清资源自带的中文字幕质量参差不齐,还不如自己下载官方字幕文件。
用Golang写这个工具,整个过程就像搭积木:请求 → 解析 → 格式转换 → 落地文件,每块都不大,但组合起来,解决了实实在在的痛点,你可能不会写Golang,没关系,思路是一样的——找到数据源,找到规律,写代码替你做重复劳动。
你瞧,代码就这么简单,没有花里胡哨的架构,没有微服务,没有容器化,就是一个main.go,一个go build,一个拿去就能用的二进制。工具不需要多高级,够用就行。
(文章完)
发表评论