2018年10月6日土曜日

YouTubeのチャンネルに登録された動画一覧を得るコード

YouTubeで適当に動画を見ていて「このチャンネルの動画最初から見てみようかな?」ってなったことありませんか? で、そのチャンネルに700本くらい動画があったら……。

YouTubeの動画の絞り込み機能って貧弱なんですよね。 特にチャンネルの動画一覧のページにある機能はほとんど何もできません。 せめて日付で絞り込む機能があればいいんですけど、現状追加日で並び替えて古い順から見てくしかないのかな? 最初の数十本はそれでいいのかもしれません。 でも700本中の300本目とか、探すだけでも大変で困ります。

そういえばずっと前にYouTubeの自分のチャンネルの動画をリストアップするコードを作ったよな? でも確かめてみると今は動かないようです。 今のやり方で作り直すしかないようです。 って事で自分用の簡単なツールをあらためて作ってみました。

API Keyの取得

以前のコードはYouTube Data APIのv1だったのかな? その頃はgdata.youtube.comに問い合わせurlを投げるだけで知りたい情報が返ってきました。 今のバージョンはv3。 「urlを投げれば情報が得られる」って部分は変わらないんですが、制限があります。 googleアカウントに紐づいたAPI Keyが無いと回答してくれなくなっています。 そして、1日に処理できる量が設定されているのです。 現時点では1日に500万ユニットまでだそうです。 (BtoBの契約とかで増やせるのかな?) ユニットというのは処理単位で、単純な問い合わせなら1ユニット消費、動画のアップロードなら1500ユニット消費というように重い処理ほど多く消費するようになっています。

こんな制限が付いたのは……「ただで使えるんならサーバーの負荷とか考えずに適当なコードで使ってやれ」みたいな人がたくさんいたんでしょうかね? それとも単純に悪用されたから? ともかく、今は誰かが「悪さ」をしたらAPI Keyを剥奪するだけで抑えられるようになってます。

ってことでまずはAPI Keyを取得しましょう。 取得にはもちろんGoogleアカウントが必要です。 取得方法はこのページに書いてあったのを参考にしました(丸投げ)

API Keyを悪用された場合、それはAPI Keyと紐づいたアカウントの持ち主の責任になる事でしょう。 悪用でなくても無関係な人に勝手に使われると処理ユニットが減ってしまいます。 API Keyは色々制限する事ができるので、勝手に使われないように制限しておいた方がよさそうです。

参考サイトには「特定のドメインからのアクセスのみAPIリクエストを受け付ける場合は……」みたいな事が書いてあります。 これは自分のサイトにjavascriptなどで問い合わせコードを埋め込んで使う場合の制限ですね。

個人で使う自分用のツールなどの場合も制限した方がいいんでしょうか? 要らない気もしますが、もし制限するならIPとかでの制限ですかね? まず、API Keyの制限設定で「127.0.0.1」などの適当なIPからのアクセス以外を弾くように設定します。 でもってgoogle chromeなどのブラウザから制限をかけたKeyを使って問い合わせをすると「IP●●からのアクセスは相手にしないよ」とエラーメッセージが返ってきます。 API Keyの制限設定をそのIPに書き換えれば自宅以外からのアクセスを弾けるようになります。 多くの場合、プロバイダから割り当てられたIPはたまに変わるので、変わるたびに制限の掛けなおしですね。 そこまでやる必要あるかな?

フリーツールなどに組み込む場合はユーザーにAPI Keyを作るように促すことになりそうです。

問い合わせのurl

YouTube Data API (v3) の概要はこちらのサイトに書いてあります。 ここを一通り読めば簡単なアプリくらいは作れるでしょう。

チャンネルに登録された動画の一覧を得るには検索(Search)機能を使います。 リファレンスはこちら。

このページの下の方にある「実際に試してみる」の項目を使えば、どんな問い合わせをすればどんな項目が返ってくるか試すことが出来ます。 Authenticationを「API Key」にして使ってみましょう。 リファレンスサイトが用意したKeyで問い合わせることが出来るので、このページで試す分には処理ユニットについて気にする必要はありません。

チャンネルに登録された動画を得るためのurlはこんな感じです。

https://www.googleapis.com/youtube/v3/search?part=snippet&type=video&fields=nextPageToken,items(id/videoId,snippet/title,snippet/publishedAt)&order=date&maxResults=50&channelId=●&key=★&publishedAfter=▲&publishedBefore=▼

  • part : 取得する項目。snippetはタイトルや概要、サムネイルなどの動画情報。
  • type : video、channel、playlistの中から必要なものだけを指定。
  • fields : ここに書いた項目だけ返ってくる。不要な情報を省くために指定。
  • order : 日付順、人気順などを指定。
  • maxResults : 一度の問い合わせで取得できる数。最大50。
  • channelId : チャンネルのページ「https://www.youtube.com/channel/●●●」を開いたときの●の部分。
  • key : API Key
  • publishedAfter : 指定した日時(UTC)以降の動画に絞り込む
  • publishedBefore : 指定した日時(UTC)以前の動画に絞り込む

fieldsの詳細は先ほどリンクを貼ったYouTube Data APIの概要に書いてあります。 リファレンスのSearch: listのページで試すには「Show Standard parameters」をクリックして表示します。

レスポンスはjson形式です。 maxResults以上の動画があった場合、レスポンスにnextPageTokenが含まれます。 その場合、同じ問い合わせでパラメータにpageToken=(前の問い合わせのnextPageToken)を追加したものを投げると続きが返ってきます。

APIを使うときの不都合な仕様

こんな問い合わせをしたらチャンネルに登録された動画の数が調べられると思ったんですが、正確な値は返ってきませんでした。

https://www.googleapis.com/youtube/v3/search?part=snippet&fields=pageInfo/totalResults&maxResults=0&type=video&channelId=●&key=★

pageInfo/totalResultsを見れば分かると思っていたんですけどね。 実際の動画数より大きな値が返ってきてしまいます。 現時点で正確な動画数の調べ方は不明です。

また、こちらのページによるとチャンネルに登録されている動画の数が多すぎるとnextPageTokenで芋づる式にすべての動画情報を得ることはできないんだそうです。

publishedAfter~publishedBeforeで短めの期間を指定してnextPageTokenが深くならないように問い合わせれば問題は回避できるんだとか。

この件については自分で確認していません。 今回は自分用の雑なツールを作るだけなので鵜呑みにしてコードを書きました。

実装したツール

チャンネルに登録された動画数も正確には分からない、芋づる式に動画情報を集めることもできないという事で、動画情報を集める期間を手入力するツールにしました。 一応前述のやり方で動画数を取得してますが、多めの数字しか取得できないようなので入力した期間が間違っていたら無駄な問い合わせで固まります。 正常系の動作しか確認してません。 Visual Studio上で動かして、バグがあったらデバッグしながら使う感じの手抜きコードです。 数回しか使わないでしょうからそんな感じで。

API Keyに不備があったらgoogleのサーバーから403エラーが飛んできます。 httpのヘッダに403、コンテンツにjsonでエラーの詳細が入っています。 このコードではエラー処理の手抜きで他の例外と一緒に握りつぶして「例外あったよ」の報告しかしてません。 エラーがあったらchromeとかのブラウザでそれっぽい問い合わせをしてエラーメッセージを見る方向で。

.Net framework 4.6.1&wpfで組みました。 あれ、4.7入ってた? まぁいいや。

ソースコードのアーカイブはData URI schemeでこのページに埋め込んであります。 ブラウザによっては左クリックするとおかしな挙動になる事もあるようです。 右クリック→名前を付けて保存をしてください。 ダウンロードが出来なかったらchromeで試してください。 試すにはプロジェクトにSystem.Runtime.Serializationの参照を追加してください。 バグとか色々不具合もあると思いますが、何かの参考になれば。