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

メイン
// 動画データ = 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重になるといきなり読むのが難しくなるけど,なんとか見てみてくださいな.
使ってみると
試しにこの再生リストのデータを取ってみますか.

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