从零开始,我用Golang写了一个在线视频Club365中文字幕爬虫,结果发现…

这事儿得从那个下雨的周末说起,我窝在沙发上刷手机,突然想找点老片子看,结果打开Club365,发现中文字幕少得可怜,不是没有,但很多不匹...

这事儿得从那个下雨的周末说起,我窝在沙发上刷手机,突然想找点老片子看,结果打开Club365,发现中文字幕少得可怜,不是没有,但很多不匹配,或者干脆放了个机翻的,我寻思着:能不能自己写个工具,把那些字幕拽下来重新整理?

说干就干,我选了Golang,为啥?因为它快,编译出来一个小小的二进制文件,扔哪都能跑,而且我喜欢它那种“吊儿郎当”但干活利索的劲儿。

第一步:摸清Club365的字幕藏在哪儿

打开Chrome的开发者工具,Network一栏,刷新页面,找啊找,找到了一个叫 subtitles.json 的文件,里头长这样:

{
  "video_id": "club365_zh_12345",
  "subtitles": [
    {"start": 0.0, "end": 3.5, "text": "嘿,好久不见。"},
    {"start": 3.5, "end": 7.2, "text": "你最近在忙什么呢?"}
  ]
}

关键点:这个JSON是一段一段的,包含每个字幕的起始时间、结束时间和文本,更骚的是,有些视频有多个语言版本的字幕——URL参数里带 ?lang=zh 就是中文,?lang=en 是英文。

我写了段Golang代码,模拟浏览器发请求:

从零开始,我用Golang写了一个在线视频Club365中文字幕爬虫,结果发现…

resp, err := http.Get("https://api.club365.com/videos/12345/subtitles?lang=zh")
if err != nil {
    log.Fatal("拉取字幕失败:", err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))

第一次跑,报错403,哦,忘了加User-Agent,加上之后,妥了。

第二步:把JSON解析成干净的字幕文件

拿到这个JSON之后,我想着转成标准的 SRT格式,这样任何播放器都能用,SRT格式长这样:

1
00:00:00,000 --> 00:00:03,500
嘿,好久不见。
2
00:00:03,500 --> 00:00:07,200
你最近在忙什么呢?

我用Golang的结构体映射JSON里的字段:

type Subtitle struct {
    Start float64 `json:"start"`
    End   float64 `json:"end"`
    Text  string  `json:"text"`
}
type SubtitleResponse struct {
    Subtitles []Subtitle `json:"subtitles"`
}

然后写了个转换函数,把秒数转成 HH:MM:SS,mmm 的格式,这里有个小坑——Golang的 time.Duration 好用是好用,但精度控制得手动搞定。

func secondsToSRTTime(seconds float64) string {
    d := time.Duration(seconds * float64(time.Second))
    return fmt.Sprintf("%02d:%02d:%02d,%03d",
        int(d.Hours()),
        int(d.Minutes())%60,
        int(d.Seconds())%60,
        int(d.Milliseconds())%1000,
    )
}

最后把字幕按序号、时间线、文本一行行写进 .srt 文件里。跑一下,完美。

第三步:批量处理——俱乐部里上百个视频的字幕

但问题来了:Club365可不是只有一两个视频,它有几百上千个啊,一个一个手动下载,手会断的。

于是我写了个循环,遍历视频ID列表,视频ID从哪里来?我发现它们的主页面里有个隐藏的JSON接口,返回所有视频的元信息,包括ID、标题、语言资源列表。

type Video struct {
    ID        string   `json:"id"`    string   `json:"title"`
    HasSubsZH bool     `json:"has_subs_zh"`
}

只下载那些 HasSubsZHtrue 的视频,然后并行处理——Golang的goroutine就是干这个的。

var wg sync.WaitGroup
for _, v := range videos {
    if v.HasSubsZH {
        wg.Add(1)
        go func(videoID string) {
            defer wg.Done()
            downloadAndSaveSubtitle(videoID)
        }(v.ID)
    }
}
wg.Wait()

并行一下,速度唰唰的。 原本逐个下载要半小时,现在3分钟搞定,但有个——并发太快,被服务器限流了,我加了个 time.Sleep(200 * time.Millisecond) 在每次请求之间,平衡了一下。

第四步:最大的问题——字幕是机翻的

下载下来的字幕,有些根本没法看,Hello, how are you”被翻成“你好怎么样你”,一看就是谷歌翻译的结果,而且还没调教好。

我寻思着能不能用更好的翻译API重新翻译?于是我接入了百度翻译API(做中文翻译公认不错的),因为我已经从Club365拿到的原文(英文)和机翻中文,现在只需要把原文再翻译一次,覆盖掉原来的中文。

type TranslationRequest struct {
    Q     string `json:"q"`
    From  string `json:"from"`
    To    string `json:"to"`
    AppID string `json:"appid"`
    Salt  string `json:"salt"`
    Sign  string `json:"sign"`
}

注意:在请求API时必须拼接签名,格式是 appid+q+salt+密钥 的MD5,这个搞错了就403,我调试了半小时才发现少了个参数。

用新翻译的文本替换原来的中文字幕,再写回文件。这一下子质量好多了,至少是通顺的自然语言了。

第五步:组织整理——让字幕能直接用在播放器里

下载好的SRT文件,我按视频标题归类:

视频ID 字幕文件路径
club365_123 星际迷航·原初 ./subtitles/星际迷航·原初.srt
club365_456 黑客帝国 ./subtitles/黑客帝国.srt
club365_789 生活大爆炸 S01E01 ./subtitles/生活大爆炸_S01E01.srt

我做了一个小脚本,扫描本地视频文件,自动匹配同名的SRT字幕,只要视频文件名和字幕文件名一致(不含扩展名),PotPlayer、MPC-BE等播放器就能自动加载。

# 示例:重命名字幕为与视频匹配
mv 黑客帝国.srt "黑客帝国.BluRay.1080p.x264.mkv.srt"

这样视频目录里的字幕就直接可用,中文用户打开直接看,不用再手动拖拽加载。

意外发现——字幕的时间轴还能自动对齐

有些字幕下下来之后,发现时间轴偏移了,比如第一句字幕出来慢了一秒,我又写了个小功能,自动批量调整时间轴偏移量。

func shiftSubtitle(subs []Subtitle, offset time.Duration) []Subtitle {
    for i := range subs {
        subs[i].Start += offset.Seconds()
        subs[i].End   += offset.Seconds()
    }
    return subs
}

可以根据第一个字幕的起始时间自动计算偏移,或者手动输入偏移量(毫秒级)。这个功能虽然小,但很常用——尤其是那些来自不同源的字幕。

关于Club365中文字幕的现状

说实话,Club365上的中文字幕质量参差不齐,有的显然是人工翻译的,用词地道,断句合理;有的就是机器瞎翻的,卡得让人想摔键盘,我的这些工具,能解决一部分问题——但不是全部。

有些字幕连对应的英文原文都没有,只有一个未知语言的声道,那就彻底没法子。遇到这种情况,我的代码只能跳过,然后默默把视频URL记录下来,等以后有资源了再补。

最后想说的

这个工具我从头到尾用Golang写,大概花了两个晚上,现在它躺在我电脑里,每次想看电影就直接跑一下,拉最新的中文字幕,挺好用的。

其实我写这篇文章不是为了炫耀什么,而是想告诉你——很多所谓的“麻烦”,用一点点代码和耐心,就能变得很顺手。 你不需要是全栈工程师,也不需要懂复杂的算法,只要你愿意折腾,边查文档边敲代码,慢慢就能搞出来。

Club365里还有很多好片子等着看,我也才整理完一半,剩下的一半,周末再说吧——不完美的工具也比没有强。

(完)

本文来自作者[kyadmin]投稿,不代表be365立场,如若转载,请注明出处:http://www.hljbesthome.com/jiankang/384.html

(15)

文章推荐

发表回复

本站作者才能评论

评论列表(4条)

  • kyadmin
    kyadmin 2026-06-27

    我是be365的签约作者“kyadmin”!

  • kyadmin
    kyadmin 2026-06-27

    希望本篇文章《从零开始,我用Golang写了一个在线视频Club365中文字幕爬虫,结果发现…》能对你有所帮助!

  • kyadmin
    kyadmin 2026-06-27

    本站[be365]内容主要涵盖:be365,be365网站,be365网址,ball365体育,Be365排名

  • kyadmin
    kyadmin 2026-06-27

    本文概览:这事儿得从那个下雨的周末说起,我窝在沙发上刷手机,突然想找点老片子看,结果打开Club365,发现中文字幕少得可怜,不是没有,但很多不匹...

    联系我们

    工作时间:周一至周五,9:30-18:30,节假日休息

    关注我们