起因

最近成为了一名 DD ,但奈何一天没有 26 个小时,所以打算写个能自动录制直播和弹幕的工具 监控器

开始动手后,发现 B 站的视频流和弹幕是真的好拿,网上也是一堆解析文章,但 YouTube 就没这么方便了,视频流在 youtube-dl 里找到了方法,评论网上只能找到使用 YouTube API 的方法,所以最后还是请出 Chrome 的 F12 大法。

分析

一般的视频网站的弹幕用的都是 WebSocket (HTML5 播放器),但 YouTube 真的是有钱任性,直接用 ajax 按时请求服务器。

入口

首先要拿到直播的 videoId ,一般就是 https://www.youtube.com/watch?v= 后面的 11 位字符串。然后抓取链接 https://www.youtube.com/live_chat?is_popout=1&v=videoId 的内容(必须带 UserAgent 要不然会跳转到不支持浏览器页面)。在抓下来的 HTML 内容中有一段 window["ytInitialData"] = {...} ,把花括号包括内容用正则匹提取出来按 JSON 格式进行解析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
...
"contents": {
"liveChatRenderer": {
"continuations": [{
"invalidationContinuationData": {
"invalidationId": {...},
"timeoutMs": 10000,
"continuation": "continuation",
"clickTrackingParams": "clickTrackingParams"
}
}]
}
}
...
}

其中 continuation 就是下一个请求的 Token, 而 timeoutMs 是下个请求需间隔的毫秒数。

经测试 videoId 中带下划线的直播 invalidationContinuationData 要替换成 timedContinuationData

拿到 continuation 后就可以开始循环请求 无限 For 制 了。

获取弹幕

带上 UserAgent 和入口请求下发的 Cookie (update:不带也能正常获取?迷惑) 请求 https://www.youtube.com/live_chat/get_live_chat?continuation=continuation&pbj=1 可以获取一段 JSON。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
{
...
"response": {
"responseContext": {...},
"continuationContents": {
"liveChatContinuation": {
"continuations": [{
"invalidationContinuationData": {
"invalidationId": {},
"timeoutMs": 10000,
"continuation": "...",
"clickTrackingParams": "..."
}
}],
"actions": [{
"addChatItemAction": {
"item": {
"liveChatTextMessageRenderer": {
"message": {
"simpleText": ""
},
"authorName": {
"simpleText": ""
},
...
"timestampUsec": "1555680252649047"
}
}
}
}]
}
}
}
...
}

actions 里每一个 addChatItemAction 都是一条评论,其中 message 是评论内容,authorName 是发送用户。之后循环在 Sleep timeoutMs 后用新 continuation 发下一次请求。

这里 invalidationContinuationData 特性和上面相同