Help us understand the problem. What is going on with this article?

【GAS】Youtube Data Apiを使ってYouTube 動画コメントを全取得する

はじめに

これは、Spreadsheets/Excel Advent Calendar 2020の25日目の記事となります。
6日遅れの大晦日に書いていますけどね。

どんだけ同じネタを使い回すのか、とはいえ、GoogleAppsScrip(GAS)版を作ってなかったんだよね。

環境

  • Windows 10 Home
  • Google.Apis.Youtube.v3 v1.49.0.2173

準備

仕様

コメントのフォーマットはhtmlかplain textがあるのですが、plain textになっています。
並び順はrelevanceで評価順が多い順にしています。子コメントについては順不動(並び順を指定しても動画サイトと同じにならない)です。

※APIの使用回数を減らすため 親コメントはmaxResults=100、子コメントはmaxResults=50とする。
※コメントでは低評価(disLike)数は取得できない。

(連番)         (親コメント) (グッド数) (投稿者名) (投稿日時) (返信数)
(連番) (子連番) (子コメント) (グッド数) (投稿者名) (投稿日時) 

使用方法

function getYouTubeComment() {
  let video_list = ['(Video IDを入力)'];
  for (let i = 0; i < video_list.length; i++) {
    let video_id = video_list[i];
    getComment(i, video_id);
  }
}

シート名には動画のタイトルがセットされます。
今回はリストになっているため、複数指定することができシートごとに動画コメントが出力されます。

let video_list = ['(Video IDを入力)', '(Video IDを入力)'];

Video IDを入力

例えば、「https://www.youtube.com/watch?v=oeJ_b0iG9lM」であれば、oeJ_b0iG9lMがVideo IDとなりますので、プログラムのVideo IDを入力で対象動画のVideo IDに書き換えてください。

プログラム

function getYouTubeComment() {
  let video_list = ['(Video IDを入力)'];
  for (let i = 0; i < video_list.length; i++) {
    let video_id = video_list[i];
    getComment(i, video_id);
  }
}

// コメント取得
function getComment(i, video_id) {
  let ss = SpreadsheetApp.getActiveSpreadsheet();
  let pageToken = '';

  let video = YouTube.Videos.list('id,snippet, statistics', {id: video_id,});

  let sh;
  if (i == 0) {
    sh = ss.getActiveSheet();
  } else {
    sh = ss.insertSheet();
  }
  sh.setName(video.items[0].snippet.title);
  sh.clear();

  let row = { value: 1 };
  let values = new Array('連番', '子連番', 'コメント', 'グッド数', '投稿者名', '投稿日時', '返信数');
  output(row, sh, values);

  let no = 1;
  while (true) {
    let comment_list = YouTube.CommentThreads.list('id, replies, snippet', {
      videoId: video_id,
      maxResults: 100,
      order: 'relevance',
      textFormat: 'plaintext',   
      pageToken: pageToken,
    });

    for (let j = 0; j < comment_list.items.length; j++) {
      // 総返信数
      let replyCount = comment_list.items[j].snippet.totalReplyCount;
      let item = comment_list.items[j].snippet.topLevelComment.snippet;
      outputItem(no, '', row, sh, item, replyCount);

      if(replyCount > 0) {
        if(replyCount == comment_list.items[j].replies.comments.length) {
          for (let k = 0; k < comment_list.items[j].replies.comments.length; k++) {
            let item2 = comment_list.items[j].replies.comments[k].snippet;
            outputItem(no, k + 1, row, sh, item2, '');
          }
        }
        else{
          // 親ID
          let parentID = comment_list.items[j].snippet.topLevelComment.id;
          getReplyComment(sh, no, row, parentID);
        }
      }
      no++;
    }

    pageToken = comment_list.nextPageToken;
    if (typeof pageToken == 'undefined') {
      break;
    }
  }
}

// 返信コメント取得
function getReplyComment(sh, no, row, parentID) {
  let cno = 1;
  let pageToken = '';
  while (true) {
    let comment_list = YouTube.Comments.list('id, snippet', {
      maxResults: 50,
      parentId : parentID,
      textFormat: 'plaintext',   
      pageToken: pageToken,
    });

    for (let j = 0; j < comment_list.items.length; j++) {
      let item = comment_list.items[j].snippet;
      outputItem(no, cno, row, sh, item, '');
      cno++;
    }

    pageToken = comment_list.nextPageToken;
    if (typeof pageToken == 'undefined') {
      break;
    }
  }    
}

// データ出力
function outputItem(no, cno, row, sh, item, replyCount) {
  // コメント
  let text = item.textDisplay;
  // グッド数
  let likeCount = item.likeCount;
  // ユーザー名
  let authorName = item.authorDisplayName;
  // 投稿日時
  let publishedAt = localDate(item.publishedAt);

  values = Array(no, cno, text, likeCount, authorName, publishedAt, replyCount);
  output(row, sh, values);
}

// Google Spread Sheetに出力
function output(row, sh, values) {
  for(let i = 0; i < values.length; i ++) {
    sh.getRange(row.value, i + 1).setValue(values[i]);
  }
  row.value++;
}

// 日本日時に変換
function localDate(dt) {
  return Utilities.formatDate(new Date(dt), 'JST', 'yyyy-MM-dd HH:mm:ss');
}

実行結果

郡司りかさんを御存知でしょうか?
マツコ・デラックスさんと村上信五(関ジャニ∞)さんがMCの「月曜から夜更かし」の中で、運動音痴として注目を浴びた女性です。
郡司りかさんはYoutubeとTwitterをやられており、ツイート画像に「おはよー」を隠すという遊びをしています。
郡司りかさんのツイート画像の「おはよー」を見つける

【NiziU】郡司さんMake You Happyにチャレンジ (練習前)」の動画コメントを取得すると、下記のようになります。
GASYoutubeAPI.png

他のプログラム言語と違い

API_KEYの指定が不要

他のプログラム言語ではAPI_KEYを指定していたのですが、Google Apps Scriptでは指定は不要でした。

返信コメントの取得

他のプログラム言語と違い返信コメントは5件までだったら、item.snippet.replies.commentsの配下で取得出来るので、それで負荷を減らしています。ほとんどの返信コメントは数件ですから、それで充分です。

最後に

初めて本格的に GoogleAppsScript と Googleスプレッドシート を使いましたけど、これは連携させるとすごく楽ですね。
仕事だとExcelメインで Googleスプレッドシートを使う機会がなかったので、さわって来なかったんだけど。
Google Colaboratory と Googleスプレッドシートで連携できそうだし積極的に使っていくことにします。

yaju
静岡県島田市在住ののシニアSE(元Microsoft MVP 2010-2012)がコンピューター、機械学習、Unity、数学について考える。
http://yaju3d.hatenablog.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away