💬
帰ってきたニコニコからコメントを取得する
祝🎉ニコニコ動画復活
バージョンが帰ってきたニコニコとなり、コメントの取得方法が変わりました。
変更点と実装など述べていきます
間違ってたらコメント下さい
過去バージョンからの変更点
コメント取得にはThreadIDとThreadKeyが必要です。
過去バージョンではidにjs-initial-watch-data
を持つdivタグがHTML内にあり、それをパースして取得していました。
新バージョンではそのdivタグがなくなり、代わりにscriptタグに埋め込まれたJSONから値を取得できるようになりました
下の実装では正規表現で抜き取っています
あと、これは新バージョンからなのかわからないんですけど、ヘッダーにx-frontend-id
を指定してあげないと400で怒られます
それ以外は多分過去バージョンと一緒です
実装
言語はTypeScript
動作確認はDeno
import { ThreadIdFetchError, ThreadKeyFetchError } from "./error.ts";
interface ThreadRequestBody{
params: {
targets: {
id: string;
fork: "owner" | "main" | "easy";
}[];
language: "ja-jp";
}
threadKey: string;
additionals: Record<string | number | symbol, never>;
}
interface ThreadResponse{
meta: {
status: number;
},
data: {
globalComments: {
id: string;
count: number;
}[];
threads: {
id: number;
fork: "owner" | "main" | "easy";
commentCount: number;
comments: {
id: string;
no: number;
vposMs: number;
body: string;
commands: string[];
userId: string;
isPremium: boolean;
score: number;
postedAt: string;
nicoruCount: number;
nicoruId: string | null;
source: "trunk" | "leaf" | "nicoru";
isMyPost: boolean;
}[];
}[];
}
}
const url = "https://www.nicovideo.jp/watch/sm34238873" //ここに取得先のURL
const endpoint = "https://public.nvcomment.nicovideo.jp/v1/threads";
const threadIdRegex = /threadIds":\[\{"id":(.*?),"/;
const threadKeyRegex = /{"threadKey":"(eyJ0eXAiOiJKV1Qi.*?)"/;
const videoPage = await (await fetch(url)).text();
const threadId = videoPage.match(threadIdRegex)?.[1];
const threadKey = videoPage.match(threadKeyRegex)?.[1];
if(!threadId){
throw new ThreadIdFetchError();
}
if(!threadKey){
throw new ThreadKeyFetchError();
}
const payload: ThreadRequestBody = {
params: {
targets: [
{
id: threadId,
fork: "owner"
},
{
id: threadId,
fork: "main"
},
{
id: threadId,
fork: "easy"
}
],
language: "ja-jp"
},
threadKey: threadKey,
additionals: {}
}
const threadResponse = await (await fetch(endpoint, {
method: "POST",
body: JSON.stringify(payload),
headers: {
"x-frontend-id": "6"
}
}));
const response = await threadResponse.json() as ThreadResponse;
参考文献
Discussion