最初に断っておくけど,素晴らしいコードではきっとないと思う.参考程度にどうぞ.

メイン
// 動画データ = id, date, view のリストを作る function getVideoData(){ // APIリクエストごとに変わらない値を入れておく var params = { maxResults : 50, playlistId : "YOUR-PLAYLIST-ID-HERE", key : "YOUR-API-KEY-HERE" } // 動画の総数を取得 var videoCount = getVideoCount(params); // 動画のIDと公開日のデータを取得 var id_date = getId_date(params, videoCount); // 取得した再生回数と id_date を結合して出力用の変数に入れる var videoData = getViewCount(params, id_date); return videoData; }
このスクリプトでは合計3種類のYouTube APIにアクセスする.2と3の処理を一緒にできないか調べてみたんだけど,できなさそうだった.面倒くさいなあ…
ちなみに maxResults=50
は,3でアクセスする video
リソースのリクエスト時にかかってくる制約.このリクエストでは最大50個までしか1回のAPIリクエストでデータを取得できないので,それ以下の値を指定します.
1: 動画総数を取得
// プレイリスト内の動画の数を取得 // https://developers.google.com/youtube/v3/docs/playlists function getVideoCount(params){ var url = "https://www.googleapis.com/youtube/v3/playlists"; url += "?part=" + "contentDetails"; url += "&id=" + params.playlistId; url += "&key=" + params.key; var res = JSON.parse(UrlFetchApp.fetch(url)); return res.items[0].contentDetails.itemCount; }
見て分かる通り,playlist
リソースにアクセスして動画の総数を取得する.APIの詳細はドキュメントを見てね.
2: 動画のIDと公開日を取得
// プレイリストから動画のIDと公開日を取得 // https://developers.google.com/youtube/v3/docs/playlistItems/list function getId_date(params, videoCount){ var url = "https://www.googleapis.com/youtube/v3/playlistItems"; url += "?part=" + "contentDetails"; url += "&playlistId=" + params.playlistId; url += "&maxResults=" + params.maxResults; url += "&key=" + params.key; // APIレスポンスを入れる変数 var data = []; // 2回目以降のAPIリクエスト時に,次のページを要求するためのトークン var pageToken = ""; // 動画の数だけデータをAPIリクエストを出す do{ // ページトークンの有無によってURLをちょっと変える var req = url; if(pageToken != "") req += "&pageToken=" + pageToken; // APIリクエストを変数に入れる var res = JSON.parse(UrlFetchApp.fetch(req)); // リクエストデータから,IDと公開日を取り出す for (var i in res.items){ data.push(res.items[i].contentDetails); } // 次のページのトークンがあれば更新 if(res.nextPageToken != "") pageToken = res.nextPageToken; } while (data.length < videoCount); return data; }
実は1つ目のAPIリクエストを実行しなくても,この playlistItem
リソースにアクセスすれば再生リスト内の動画の総数は分かるんだよね.でもこの関数の内容が妙に複雑になる (19行目から始まるループの初回だけ再生数を取得する処理を入れなきゃいけない) のが嫌だったので,こういう構成にしてみました.
3: 動画IDから再生数を取得
// 取得した再生回数と id_date を結合して出力用の変数に入れる function getViewCount(params, id_date){ // id のカンマ区切りリストを作る var idList = makeIdList(params, id_date); // 出力用の変数 var videoData = []; // maxResults 個ずつAPIリクエストでデータを取得 for (var i in idList){ // APIのエンドポイントとパラメータ var url = "https://www.googleapis.com/youtube/v3/videos"; url += "?part=" + "statistics"; url += "&id=" + idList[i]; url += "&fields=" + "items%2Fstatistics"; url += "&key=" + params.key; // idList に ID が含まれる動画のデータを取得 var res = JSON.parse(UrlFetchApp.fetch(url)); // 取得した再生回数と id_date を結合して出力用の変数に入れる for (var j in res.items) { var stats = { id : id_date[Number(i)*params.maxResults + Number(j)].videoId, date : id_date[Number(i)*params.maxResults + Number(j)].videoPublishedAt.slice(0, 10), view : Number(res.items[j].statistics.viewCount) } videoData.push(stats); } } return videoData; }
これがやたらと複雑.ここの処理をどう書いたらいいのか分からず,結構な時間悩んだ.video
リソースの part=statistics
から動画の再生数を取得できるんだけど,動画IDを1回のAPIリクエストで最大で50個までしか送ることができない.
再生リスト内に51個以上の動画がある場合は,2で取得したIDの50個ずつに分けて連結して,それをGET
パラメータに載せる必要がある.まずはその処理をやってますね.
ちなみに,29行目では取得した公開日情報のテキストを .slice(0, 10)
で切り取ってる.もともと例えば YYYY-MM-DDThh:mm:ss.sZ
みたいな形式 (ISO 8601 形式と言うらしい) の string
が入ってるんだけど,僕の場合は時刻は要らないので (というか時刻情報載ってない?) ,それを切り取って YYYY-MM-DD
だけ取り出してます.
3′: IDを maxResults 個ずつに分けて結合
// 動画のIDを maxResults 個ずつに分割して,それぞれをコンマ連結のテキストにする function makeIdList(params, id_date){ var length = id_date.length; // 動画の数 var loops = Math.ceil(length/params.maxResults); // 外側ループの回数.動画が130個なら3回ループが要る var idList = []; // 出力用の変数 // 外側ループ for (var i=0; i < loops; i++){ // IDのコンマ連結を入れる変数 var idText = ""; // maxResults 個ずつに分けて動画IDのコンマ連結を作る for (var count=0; count < params.maxResults; count++){ // コンマ連結を作る try { idText += id_date[params.maxResults*i + count].videoId + ","; } // 最後のループ (i = loops-1) では maxResults 回も繰り返す必要がないので,その場合はループを抜ける // 例えば maxResults=50 なら, // 0<id<49 (i=0), 50<id<99 (i=1), 100<id<149 (i=2), ... という感じ catch(e) { break; } } // 末尾に不要なコンマを付けているので,削除してリストに追加 idList.push(idText.slice(0, -1)); } return idList; }
for
が2重になるといきなり読むのが難しくなるけど,なんとか見てみてくださいな.
使ってみると
試しにこの再生リストのデータを取ってみますか.

簡単!便利 (?) !楽しい!
コメントを残す