ビリビリ動画のAPIで、動画の再生数をGoogleスプレッドシートに自動収集してみた

ビリビリ動画のAPIを見つけたので、ちょっと触ってみました。
https://www.bilibili.com/read/cv3430609/

やりたいこと:
ビリビリ動画の特定のチャンネルを対象に、アップされている動画をスプレッドシートでリスト化し、それぞれ再生数を毎日取得する。新しい動画が投稿されていたら、その動画のタイトル・URLをリストに追加する。

こっち1年、仕事の合間にGoogle Apps Scriptをちまちま勉強していたので、今回もGASを使っていきます。

まずは、特定のチャンネルにアップされた動画情報を収集します。

"http://space.bilibili.com/ajax/member/getSubmitVideos?mid=【チャンネルID】&;pagesize=【ページサイズ】&page=【ページ番号】"
こいつを叩くと、指定したチャンネルの情報が取れます。アップロードされている動画のIDや再生数、コメント数など一通りの情報がjsonで取れます。毎日スクリプトを起動させて、新しい動画が追加されていたら、スプレッドシートの最終行に追加してくれます。

試しに、キズナアイ中国版のチャンネル「AIChannel中国绊爱」で叩いてみると、以下の通りです。

画像1

赤い下線を付けている「aid」が、各動画のIDです。このIDを取り出して配列を作って、今度は各動画の情報を取りに行きます。UrlFetchAppからのJSON.parseしました。

続いて、動画ごとの情報を取り出すには、下記のURLでAPI叩いてください。

"https://api.bilibili.com/x/web-interface/view?aid=【動画ID】"
これで取り出せるjsonは下記の通り。「title」は動画タイトル、「view」は再生数です。その他、「danmaku」「favorite」「coin」など色々あります。

画像2

で、これをまたUrlFetchAppからのJSON.parseです。あとは配列とかを上手いこと使ってやればおk。取り出した情報を整形して、スプレッドシートに自動で追加していきます。アウトプットのイメージが下記。

画像3

まっさらなスプレッドシートを用意して、赤丸で囲ったB1セルに、調査対象のチャンネルのURLを入れて下さい。他のところは空白セルで。あとはスクリプトを起動させれば、自動で動いてくれる設定になっています。ちなみに、A列が各動画のタイトルで、B列がIDです。

ちなみに、削除されているのにチャンネルの動画一覧に情報が残ってしまっている動画があります。例えば、下記の赤丸の動画。アクセスすると、エラー画面に飛ばされてしまいます。

画像4

こういう動画は、そのままだと動画情報を読みに行けずにエラーを吐いてしまうので、「try~catch(e)」で対応しています。

ただ、前まではアップされていたのでリストにあるけど、削除されてしまった、というケースに対応する必要がありそうなので、そういう場合はタイトルに「deleted」、再生数に「0」を入れる処理も入れていますが、この辺実際にどう動くか分かんない。改善の余地がありそう。

で、実際のコードが下記です。多分無駄なところだらけな気がするので、ツッコミお待ちしております。関数「newVideoDetect」を使ってください。

①トリガーを削除(triggerDelete)
②新しい動画がアップされている場合はリストに追加(newVideoDetect)
③再生数を取得(videoResearch)
④動画タイトルを取得(titleCollect)
⑤24時間後に自動で起動するようトリガーをセット(triggerSet)

という流れです。
var sheet = ss.getSheetByName("*シート名を記載");
これが3箇所あるので、任意のシート名に書き換えて使ってね。

function newVideoDetect() {
 triggerDelete();
 var ss = SpreadsheetApp.getActiveSpreadsheet();
 var sheet = ss.getSheetByName("*シート名を記載");
 var lastRow = sheet.getLastRow();
 var date = new Date();
 for (var k = 1; k <= 10; k++) {
   var array = new Array();
   var nameArray = new Array();
   var channelId = sheet.getRange(1, 2).getValue().slice(27);
   try {
     var url = "http://space.bilibili.com/ajax/member/getSubmitVideos?mid=" + channelId + "&;pagesize=1&page=" + k;
     var json = UrlFetchApp.fetch(url).getContentText();
     var jsonData = JSON.parse(json);
     for (var i = 0; i <= 19; i++) {
       try {
         var list = jsonData.data.vlist[i].aid;
         var url = "https://api.bilibili.com/x/web-interface/view?aid=" + list;  
         var nameJson = UrlFetchApp.fetch(url).getContentText();  
         var nameJsonData = JSON.parse(nameJson);  
         var title = nameJsonData.data.title;
         if (lastRow - 1 === 0) {
           array.push([list]);
           nameArray.push(title);
         } else {
           var flagUrlSet = sheet.getRange(2, 2, lastRow - 1, 1).getValues();
           flagUrlSet = flagUrlSet.concat.apply([], flagUrlSet);
           if (flagUrlSet.indexOf(list) === -1) {
             array.push([list]);
           }
         }
       } catch (e) {}
     }
     var lastRow = sheet.getLastRow();
     sheet.getRange(lastRow + 1, 2, array.length, 1).setValues(array);
     sheet.getRange(2, 1, nameArray.length, 1).setValues(nameArray);
   } catch (e) {}
 }
 videoResearch();
 titleCollect();
 triggerSet();
}

function videoResearch() {
 var ss = SpreadsheetApp.getActiveSpreadsheet();
 var sheet = ss.getSheetByName("*シート名を記載");
 var lastRow = sheet.getLastRow();
 var date = new Date();
 var rng = sheet.getRange(2, 2, lastRow - 1, 1);
 rng.setNumberFormat("0");
 var flagUrlSet = sheet.getRange(2, 2, lastRow - 1, 1).getValues();
 flagUrlSet = flagUrlSet.concat.apply([], flagUrlSet);
 var array = new Array();
 array.push([date]);
 var nameArray = [];
 for (var i = 0; i <= flagUrlSet.length - 1; i++) {
   try {
     var url = "https://api.bilibili.com/x/web-interface/view?aid=" + flagUrlSet[i];
     var json = UrlFetchApp.fetch(url).getContentText();
     var jsonData = JSON.parse(json);
     var title = jsonData.data.title;
     var view = jsonData.data.stat.view;
     array.push([view]);
     nameArray.push([title]);
   } catch (e) {
     array.push([0]);
     nameArray.push(["deleted"]);
   }
 }
 sheet.getRange(1, sheet.getLastColumn() + 1, sheet.getLastRow(), 1).setValues(array);
 sheet.getRange(2, 1, sheet.getLastRow() - 1, 1).setValues(nameArray);
}

function triggerSet() {
 var date = new Date();
 date.setHours(date.getHours() + 24); //24時間後
 ScriptApp.newTrigger('newVideoDetect').timeBased().at(date).create();
}

function triggerDelete() {
 var triggers = ScriptApp.getProjectTriggers();
 for (var i = 0; i < triggers.length; i++) {
   if (triggers[i].getHandlerFunction() == "newVideoDetect") {
     ScriptApp.deleteTrigger(triggers[i]);
   }
 }
}

function titleCollect() {
 var ss = SpreadsheetApp.getActiveSpreadsheet();
 var sheet = ss.getSheetByName("*シート名を記載");
 var rng = sheet.getRange(2, 2, sheet.getLastRow() - 1, 1);
 rng.setNumberFormat("0");
 var idSet = sheet.getRange(2, 2, sheet.getLastRow() - 1, 1).getValues();
 var array = new Array();
 Logger.log(idSet);
 for (var k = 0; k <= idSet.length - 1; k++) {
   try {
     var videoId = idSet[k];
     var url = "https://api.bilibili.com/x/web-interface/view?aid=" + videoId;
     var json = UrlFetchApp.fetch(url).getContentText();
     var jsonData = JSON.parse(json);
     var title = jsonData.data.title;
     array.push([title]);
   } catch (e) {
     array.push(["deleted"])
   }
 }
 sheet.getRange(2, 1, idSet.length, 1).setValues(array);
}

この記事が気に入ったらサポートをしてみませんか?