【GAS超実践】TwitterのAPIを叩いてチャネルの情報を自動取得する - ③ チャンネルの動画一覧を取得してみる
今日のゴール
TwitterAPIのsearchメソッドを使って、「森内チャンネル」の動画一覧を取得して、「森内チャンネル」のシートを作ってそこに自動的に書き込んでいきます。
1. 予め用意した「チャンネル情報取得」というボタンをクリックすると...
2. 森内チャンネルのシートが作成されて、全動画のID/名前/公開日時を自動的に書き込んで行きます
はじめに
まず、TwitterAPIを使うにはAPIキーが必要となりますので、この発行がまだの方は、以下のnoteを参考に取得しておいてください。
チャンネル内の動画の情報を一気に取得する方法はない?
前回の記事で、チャンネルの情報(登録者数や動画数・総視聴回数)などを取得しました。
できれば、このチャンネル内の動画を一気に取得してそれぞれの動画情報(タイトル・公開日・視聴回数・高評価・低評価・コメント数)がほしかったのですが、一気に取得することは無理っぽかったので以下の手順で取得します。
(※ 黒字のタイトルと公開日だけはsearchメソッドで取得可能です)
1. searchメソッドを使ってチャンネルの動画一覧を取得(このときに動画IDを取得)
2. videoメソッドを使って、1で取得した全動画の詳細情報を動画IDを使って取得していきます
今回は1のsearchメソッドを使ってチャンネルの動画一覧を取得していく方法を紹介します。
1. searchメソッドを使ってみる
では、searchメソッドのリファレンスを確認してみましょう。
今回の目的は森内チャンネルで公開済みの動画一覧を取得することです。searchメソッドを使うと動画の検索ができますが、その際に「特定のチャンネルの動画」を取得するパラメータが含まれます。
それが【channelId】ですね。
では、このsearchメソッドはどんなレスポンスを返してくれるのでしょうか?今回は「動画のID」「動画のタイトル」「公開日」が欲しいですね。まずレスポンスに指定可能なpartを見てみましょう。
ふむふむ。idとsnippetが指定可能ですね。
idの中に、videoIdを発見しました。これが動画IDです(次の講座で利用します)
snippetの中に、「動画の公開日」と「動画のタイトル」を見つけました。これで完璧ですね。
一応、チャンネル名も取得できるようですね。
リクエストパラメータは、partと、channnelId以外に何が必要でしょうか?searchメソッドをよく見てみると、maxResultsというパラメータがあります。この説明に「0以上50以下の値を指定できます」と書いてます。
これは、最大で50件までしか取れないよ。ということを意味してます。
(50件以上の場合、pageTokenパラメータを使いますが、それはまた今度)
さらに、普通に検索結果には、チャンネルやプレイリストも含まれてしまうので、videoだけが取得できるように、typeパラメータで、videoを指定します。
さぁ、下準備は完璧ですね。では実際にリクエストURLを作って、リクエストしてみましょう。
先程までのリクエストパラメータをもとに「part」と「channnelId」「maxResults」「type」を指定します。
https://www.googleapis.com/youtube/v3/search?key=【あなたのAPIキー】&part=snippet,id&channelId=UCAwDrM75UAddwluabae4A6g&maxResults=50&type=video
実際にブラウザで見てみましょう。
動画IDが、idパラメータの中に、公開日時,動画名,チャンネル名がsnippetの中で取得できてるのがわかります。
ではこれをGASを使ってリクエストして結果を取得してみましょう。
function searchVideos() {
// ベースとなるYoutubeAPIのURL
const baseYoutubeAPIUrl = "https://www.googleapis.com/youtube/v3/"
// 前回取得したAPIキー
const key = "【あなたのAPIキー】"
// 森内チャンネルのチャンネルID
let channelId = "UCAwDrM75UAddwluabae4A6g"
// 森内チャンネルの動画一覧を検索
// search APIは最大でも50件までしか取得できないので注意
const youtubeAPIUrl = `${baseYoutubeAPIUrl}search?key=${key}&part=snippet,id&channelId=${channelId}&maxResults=50&type=video`
let json = UrlFetchApp.fetch(youtubeAPIUrl)
let result = JSON.parse(json)
console.log(result)
}
今回はsearchVideosメソッドという名前で作ってみました。
上から順に説明していきましょう。
まずここで、リクエストに必要なURLを組み立てるのに必要な変数を用意します。
// ベースとなるYoutubeAPIのURL
const baseYoutubeAPIUrl = "https://www.googleapis.com/youtube/v3/"
// 前回取得したAPIキー
const key = "【あなたのAPIキー】"
// 森内チャンネルのチャンネルID
let channelId = "UCAwDrM75UAddwluabae4A6g"
次に、実際にリクエストするURLを組み立てています。
// 森内チャンネルの動画一覧を検索
// search APIは最大でも50件までしか取得できないので注意
const youtubeAPIUrl = `${baseYoutubeAPIUrl}search?key=${key}&part=snippet,id&channelId=${channelId}&maxResults=50&type=video`
最後に、UrlfetchAppのfetchメソッドを使ってAPIにリクエストをして、結果をJSON.parseでプログラムで扱える形にしています。
let json = UrlFetchApp.fetch(youtubeAPIUrl)
let result = JSON.parse(json)
console.log(result)
これのログはどんな感じになるでしょうか?
itemsの中に、idとsnippetが[object]で含まれてますが、中身は先程ブラウザでみたときのものが入っています。
ではでは、このitemsの中が2次元配列になっていますので、中をループで取得してみます。
配列をループで扱うには「for in」「for of」「forEach」などがありましたが、今回は「for of」を使うことにします。
for (let item of result.items) {
let videoId = item.id.videoId // 動画ID
let title = item.snippet.title // 動画名
let publishedAt = item.snippet.publishedAt // 公開日時
console.log(videoId, title, publishedAt)
}
ちゃんと各動画の、動画ID・動画名・公開日時が取得できてますね。
2. チャンネル名のシートを作ってみる
さて、せっかく上の処理で森内チャンネルで公開済みの動画の詳細が取得できたので、「森内チャンネル」用のシートを作ってみましょう。
まずはシートを作る関数を別で【createSheetByName】という名前で作ってみましょう。
/**
* チャンネル用のシートを作る
*/
function createSheetByName(sheetName) {
let spreadSheet = SpreadsheetApp.getActive()
let sheet = spreadSheet.getSheetByName(sheetName)
if (!sheet) {
spreadSheet.insertSheet(sheetName)
}
}
これも一応解説します。
最初のcreateSheetByName(sheetName)の、「()」の中のsheetNameとは、関数のときに勉強した【引数】です。この関数は【引数】にtitleという変数を受け取ることで、関数の中の処理に使えます。
※ 余談ですが、関数名や引数は極力分かりやすくしましょう。今回のようにシートを作る役割を持った関数の場合は「createSheetByName」のように、「引数の名前を使って、シートを作る」というのが直感的に分かりやすい名前にしておくとGoodです。
function createSheet(title) {
ここはおなじみですね。SpreadsheetAppのgetActiveで今アクティブなスプレッドシートオブジェクトを取得。
さらに、getSheetByName で、引数で受け取ったシート名のsheetオブジェクトを用意します。
let spreadSheet = SpreadsheetApp.getActive()
let sheet = spreadSheet.getSheetByName(sheetName)
シートを作るにはspreadSheetオブジェクトのinsertSheetメソッドを使いますが、すでにシートが存在してる状態で、実行するとエラーになりますので、シートが無い時だけ、実行してます。
ちなみに、この上のgetSheetByNameの結果から、空の場合はnullを返すことはドキュメントを見ればわかります。
If multiple sheets have the same name, the leftmost one is returned. Returns null if there is no sheet with the given name.
// シートが存在しないときだけ作る
if (sheet === null) {
spreadSheet.insertSheet(sheetName)
}
ではこの自作した関数を使って、もとのsearchVideosメソッドの中でシートを作ってみましょう。
チャンネル名はsnippetのchannelTitleで取得できることが確認できてますのでこれを使います。
// チャンネル名
let channnelTitle = result.items[0].snippet.channelTitle
// チャンネル名のシートを作る
createSheetByName(channnelTitle)
新しくチャンネル名のシートが作成されました!
3. チャンネル名のシートに動画一覧を書き込んで見る
ではいよいよ、この新しく作ったシートに動画の情報を書き込んでいきましょう。
まずはいきなり結果を見てみましょう。
// 動画一覧情報を入れる配列
let videos = []
for (let item of result.items) {
let videoId = item.id.videoId // 動画ID
let title = item.snippet.title // 動画名
let publishedAt = item.snippet.publishedAt // 公開日時
// 動画一覧の配列に追加していく
videos.push([videoId, title, publishedAt])
}
// 先程作ったチャンネル名のシートを取得
let spreadSheet = SpreadsheetApp.getActive()
let sheet = spreadSheet.getSheetByName(channelTitle)
// シートのヘッダー行のデータ
let headers = [["動画ID", "動画名", "公開日時"]]
// シートのヘッダー行にデータを入れる
sheet.getRange(1,1,1,headers[0].length).setValues(headers)
// シートの2行目から、動画の数分の行数だけrangeオブジェクトを取得し、先程集めたvideos配列をsetValuesで入れる
sheet.getRange(2,1,videos.length,videos[0].length).setValues(videos)
ここは、先程のループ処理の部分ですが、最終的にシートに対してsetValuesでデータを入れるために、動画の情報を2次元配列に入れていってます。
// 動画一覧情報を入れる配列
let videos = []
for (let item of result.items) {
let videoId = item.id.videoId // 動画ID
let title = item.snippet.title // 動画名
let publishedAt = item.snippet.publishedAt // 公開日時
// 動画一覧の配列に追加していく
videos.push([videoId, title, publishedAt])
}
ここは、先程作ったばかりのチャンネル名のsheetオブジェクトを取得して、そこに対してヘッダー行を入れてます。
ちなみに、getRange(1,1,1,headers[0].length)というのは、getRangeは引数に(開始行数,開始列数,何行分,何列分)という順番に引数を受け取りますので、1行目の1列目から、1行分のみ。ヘッダーのデータ数のみ。という形で取得してます。
最後のヘッダーのデータ数とは、headersの1つめの要素の数だけ取得してます。
// 先程作ったチャンネル名のシートを取得
let spreadSheet = SpreadsheetApp.getActive()
let sheet = spreadSheet.getSheetByName(channelTitle)
// シートのヘッダー行のデータ
let headers = [["動画ID", "動画名", "公開日時"]]
// シートのヘッダー行にデータを入れる
sheet.getRange(1,1,1,headers[0].length).setValues(headers)
これと同じ要領で、先程のvideosも入れていきます。
// シートの2行目から、動画の数分の行数だけrangeオブジェクトを取得し、先程集めたvideos配列をsetValuesで入れる
sheet.getRange(2,1,videos.length,videos[0].length).setValues(videos)
ちゃんとデータが書き込まれました!
4. 動画一覧情報を取得するボタンを作ってみる
では最後です。ボタンを押したら自動でデータ取得して、シートに書き込みしてくれるようにしてみましょう。
まずはチャンネル一覧のシートで「挿入」→「図形描画」を選びます。
次に、好きな図形を選びます。
パワポと同じ要領でボタンに文字を作り、できたボタンを右クリックして、見えづらいですが右上の点3つをクリックして、「スクリプトを割り当て」を選択します。
最後に、先程つくっていた「searchVideos」が実行されるようにして完成です。
ボタンを押してみましょう!
実行中ですね
完了しました!森内チャンネルのシートが自動で作られて、動画一覧情報が書き込まれてるのがわかります。
お疲れさまでした!
今回のコードの最終形
function searchVideos() {
// ベースとなるYoutubeAPIのURL
const baseYoutubeAPIUrl = "https://www.googleapis.com/youtube/v3/"
// 前回取得したAPIキー
const key = "【あなたのAPIキー】"
// 森内チャンネルのチャンネルID
let channelId = "UCAwDrM75UAddwluabae4A6g"
// 森内チャンネルの動画一覧を検索
// search APIは最大でも50件までしか取得できないので注意
const youtubeAPIUrl = `${baseYoutubeAPIUrl}search?key=${key}&part=snippet,id&channelId=${channelId}&maxResults=50&type=video`
let json = UrlFetchApp.fetch(youtubeAPIUrl)
let result = JSON.parse(json)
// チャンネル名
let channelTitle = result.items[0].snippet.channelTitle
// チャンネル名のシートを作る
createSheetByName(channelTitle)
// 動画一覧情報を入れる配列
let videos = []
for (let item of result.items) {
let videoId = item.id.videoId // 動画ID
let title = item.snippet.title // 動画名
let publishedAt = item.snippet.publishedAt // 公開日時
// 動画一覧の配列に追加していく
videos.push([videoId, title, publishedAt])
}
// 先程作ったチャンネル名のシートを取得
let spreadSheet = SpreadsheetApp.getActive()
let sheet = spreadSheet.getSheetByName(channelTitle)
// シートのヘッダー行のデータ
let headers = [["動画ID", "動画名", "公開日時"]]
// シートのヘッダー行にデータを入れる
sheet.getRange(1,1,1,headers[0].length).setValues(headers)
// シートの2行目から、動画の数分の行数だけrangeオブジェクトを取得し、先程集めたvideos配列をsetValuesで入れる
sheet.getRange(2,1,videos.length,videos[0].length).setValues(videos)
}
/**
* チャンネル用のシートを作る
*/
function createSheetByName(sheetName) {
let spreadSheet = SpreadsheetApp.getActive()
let sheet = spreadSheet.getSheetByName(sheetName)
// シートが存在しないときだけ作る
if (sheet === null) {
spreadSheet.insertSheet(sheetName)
}
}
実践編で利用するための基礎編はすべて無料公開してます。 基礎編のモチベーション向上のためにサポートして頂けるとめちゃくちゃ喜びます!! だいたい作業工数は1記事あたり4-5時間程度かけて【分かりやすい】【知識が身につく!】を意識して作っておりますので、今後も頑張っていきます!