50 個まではこれでいける
constAPI_KEY="";constgetYouTube=async(api,query)=>await(awaitfetch(`https://www.googleapis.com/youtube/v3/${api}${Object.entries(query).reduce((p,[k,v],i)=>`${p}&${k}=${v}`,`?key=${API_KEY}`)}`)).json();constgetVideos=async(channelId,pageToken="")=>{constplaylistId=(awaitgetYouTube("channels",{part:"contentDetails",id:channelId,})).items[0].contentDetails.relatedPlaylists.uploads;returnawaitgetYouTube("playlistItems",{part:"snippet",maxResults:50,playlistId,pageToken,});};getVideos(// https://www.youtube.com/channel/{これ}"UCsLiV4WJfkTEHH0b9PmRklw").then(console.log);
チャンネル動画だけが入ったプレイリストを取得してきて、その動画を取得する。
間髪入れずに 2 回連続リクエストするのが不安なら、リクエストの合間にawait new Promise((r) => setTimeout(r, 3000));
を入れたらいいと思う。
動画数は一度のリクエストでは 50 個までなので、
本当に全部取りたいなら nextPageToken
を使って適宜実装する必要がある。
というわけで、全部とる
constgetAllVideos=async(channelId,cooldown=3000)=>{let[all,token]=[[]];while(1){const{items,nextPageToken}=awaitgetVideos(channelId,token);all=[...all,...items];if(!nextPageToken)break;token=nextPageToken;awaitnewPromise((r)=>setTimeout(r,cooldown));}returnall;};getAllVideos(// https://www.youtube.com/channel/{これ}"UCkvvFbRyfvENnl_G8YHuriQ").then(console.log);
これで根こそぎ取ってくれる。cooldown
で指定したミリ秒によって、次のレスポンスを遅らせてるので、
これを小さくするのはおすすめできない。
気づいたこと
どうも、チャンネル ID の prefix がUC
になっている場合、
プレイリスト ID はチャンネル ID の prefix をUU
にするだけでいいらしい。
https://www.youtube.com/channel/UCQbL0aAYEmzAbvgBn2PAy4A
↓
U C QbL0aAYEmzAbvgBn2PAy4A
↓
U U QbL0aAYEmzAbvgBn2PAy4A
↓
https://www.youtube.com/playlist?list=UUQbL0aAYEmzAbvgBn2PAy4A
だからこれでもいけちゃうっぽい
constgetVideos=async(channelId,pageToken="")=>{constplaylistId=channelId.replace(/^UC/,"UU");// <--returnawaitgetYouTube("playlistItems",{part:"snippet",maxResults:50,playlistId,pageToken,});};
2 回も連続でリクエスト飛ばすよりも、こっちのほうが 1 発で済むので安心かも。
Node.js でデモコードを試す場合の注意点
Node.js では fetch が使えません。
なので、素直に axios や node-fetch を使うなり、deno を使うなりしてください。
面倒くさい人はこれを使えばとりあえず動くんじゃない(適当)
constfetch=async(url)=>newPromise((resolve,reject)=>{constreq=require("https").get(url,(res)=>{letresponse="";res.on("data",(chunk)=>{response+=chunk;});res.on("end",()=>{resolve({json:()=>Promise.resolve(JSON.parse(response)),});});});req.on("error",(e)=>reject(e));req.end();});