youtubeの動画情報を下記のURLを入れるとゲットすることができました。
https://www.googleapis.com/youtube/v3/videos?id=WTLQQPBPL1U&key=【APIキー】&part=id, snippet, contentDetails, player, recordingDetails, statistics, status, topicDetails
上のhttpsのURLをブラウザに入れると
動画IDの情報が入手できる(ブラウザに表示される)のですが、その中から
"statistics": {
"viewCount": "1840904",
"likeCount": "1814",
"dislikeCount": "279",
"favoriteCount": "0",
"commentCount": "86"
},
上のviewcountの部分だけを抜き出す方法がわかりません。
Jqueryでやるサイトを見つけましたが、外部サイトが
上のURL(youtubeの動画を習得するページ)の場合どうやるのかよく理解できませんでした。
例)
http://qiita.com/yumetodo/items/00b37234cb86e741f0fb
javascriptでviewcountの部分を抜き出し、htmlに書き出す方法を教えて下さい。
こんな感じ。
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> <script> $(function() { var apikey = "【APIキー】"; var video_id = "WTLQQPBPL1U"; var url = "https://www.googleapis.com/youtube/v3/videos?id=" + video_id + "&key=" + apikey + "&part=statistics"; $.getJSON(url, function(data) { // viewCount を取り出し var count = data.items[0].statistics.viewCount; // HTML に出力 $("#count").text(count); }); }); </script> <div id="count"></div>
viewCount だけが欲しいのであれば、URL の part= の部分は statistics だけで大丈夫です。
jsFiddle で試したのがこちら。
https://jsfiddle.net/keysgxhz/
ありがとうございました!無事成功しました。
次はvideo IDを別にリスト化してそこから
対応するIDごとに再生回数だけをピックアップするのに挑戦してみます!
$.getJSON は、非同期で処理されるので、リスト化した video ID の順番に表示をしたい、ということだと、ひと工夫必要です。
だいたいは呼び出した順番になるとは思いますが。
a-kuma3さん、ありがとうございます。1つアイデアがあり、同じことををEXCELのパワークエリで試しています。パワークエリの空のクエリから= Json.Document(Web.Contents("https://www.googleapis.com/youtube/v3/search?key={API KEY}=サッカー&part=id,snippet&maxResults=50"))
を実行すると例えば、サッカーのキーワードに関連する動画一覧が50個出ます。
しかし、このクエリ結果一覧には動画の再生回数が紐付いていません。
この1つ1つの動画に紐付いたview countをリンクさせて表示させたいと考えています。
最初のクエリで得られた動画の再生回数を得るために、別のクエリを使いました。
(このクエリの結果一覧の中を開いて見ていくとview countのデータが入っています)
= Json.Document(Web.Contents("https://www.googleapis.com/youtube/v3/videos?id={動画ID}&key={API KEY}&part=id, snippet, contentDetails, player, recordingDetails, statistics, status, topicDetails"))
ただし、この2つめのクエリは1つ1つの動画IDに紐付いているためクエリを実行するためには1つ1つの動画IDが必要です。動画IDに一番の上で得たクエリの結果の動画IDを使うことはできるのでしょうか?
つまり、1つめのクエリの結果一覧で得られた動画IDを2つめのクエリの動画IDとして使いたい。
クエリをマージするのでしょうか?1つめのクエリで得られた結果の動画IDを一度テーブル化して、そのセルの結果を2つめのクエリで参照するようなことはできますか?
search API の part って、id と snippet しか受け付けないんですね (´・ω・`)
Excel のパワークエリじゃ難しいんじゃないでしょうか。
search API を part=id で呼び出して手に入った videoId で、videos API を呼びまくるしかないと思います。
最終的に、どんな形でデータを保存したいかによると思いますが、以下のどちらかになるんじゃないでしょうか。
ぼくがやるなら、後者。
VBA あんまり好きじゃないから :-p
あと、API の呼び出し回数の制限があるので注意。
YouTube Data API Overview | YouTube Data API | Google Developers
part パラメータに指定した分だけ消費していくようです。
一回、データが手に入ってしまえば用済み、というのであれば、制限に引っかかったら日を改めて次から実行、で良いと思いますが、定期的に更新したい、ということであれば、不要な情報は part パラメータから抜いておいた方が良さそうです。
なるほど、やはり難しそうですね。1つのクエリで一度に全部のデータをゲットできたらいいのですが、それぞれ別々に分かれているので困っていました。
やはり一度ゲットした動画一覧からそのID1つ1つに対応するview countを入手するしか方法はなさそうですね。頻繁に更新はしないのですが
回数制限にかからないように気をつけてやってみます。
とりあえず、javascriptで動画一覧から動画IDを配列に入れて、その配列データを元に、再度APIで呼び出して必要なパラメーターを入手する方法で挑戦してみます。
またわからないことがありましたら教えて下さい。ありがとうございました!
a-kuma3さん、また教えて下さい。昨日はいろいろAPIの実験をしていたらあっという間にAPIのデータの制限に達してしまいました。本日再トライです。
始めに、キーワードで動画を50個検索し、その動画IDを配列に入れました。次に、その配列の中から1つづつ動画IDを読みだし$.getJSON(url1, function(data) を使って、必要なパラメーターを抜き出しました。
ただ1つ疑問点が有り、動画の再生回数や、チャンネル登録数などの数値が毎回異なるのです。もしかして、javascriptで50回ループを回している時にデータを取り損ねた?と思ったのですが毎回異なる数字はいったいどこから来ているのもか疑問です。Jsfiddleで1つ1つ動画IDを入れて試した際は成功していますが、連続でやるとなぜか結果が毎回異なります。原因はわかりますか?
スクリプトはこんな感じです。
//**************************************
//キーワード (入力したキーワードで検索)
var url1 = "https://www.googleapis.com/youtube/v3/search?key="+apikey+"&q="+inputkeyword+"&part=snippet&maxResults=50"
$.getJSON(url1, function(data) {
console.log(data);
for (var i=0; i<49; i++){ //全体を50回繰り返す(スタート行)
var videotitle= data.items[i].snippet.title
var channeltitle= data.items[i].snippet.channelTitle
var channelid= data.items[i].snippet.channelId
var videoid= data.items[i].id.videoId
//キーワードで検索した50個の動画のタイトル、チャンネル名&ID、動画IDを配列に入れる
videotitleArray.push(videotitle)
videoidArray.push(videoid)
channeltitleArray.push(channeltitle)
channelidArray.push(channelid)
} //全体を50回繰り返す(終わりの行)
}); //getJSON終わり
alert("動画IDを習得しました")
for (var i=0; i<49; i++){ //全体を50回繰り返す(スタート行)
//****動画IDごとに再生回数をゲット
var url2 = "https://www.googleapis.com/youtube/v3/videos?id="+videoidArray[i]+"&key=" + apikey + "&part=statistics";
$.getJSON(url2, function(data) {
console.log(data);
var count= data.items[0].statistics.viewCount
//キーワードで検索した50個の動画のタイトルごとの再生回数を配列に入れる
saiseikaisuuArray.push(count)
}); //getJSON終わり
} //全体を50回繰り返す(終わりの行)
alert("再生回数を習得しました")
連続でやるとなぜか結果が毎回異なります。原因はわかりますか?
スクリプトはこんな感じです。
「こんな感じ」と、試している実物は随分違うと思うのですが。
まず、「こんな感じ」のままでは、再生回数がひとつも取れないと思います。
再生回数をとる 50回のループは、キーワード検索の $.getJSON の function の中に入っているはずです。
実物がそんな感じだとして、video id と再生回数の対応が毎回違う、ということですよね。
であれば、多分、50回のループが $.getJSON の function の中に入っているのと同じ理由です。
$.getJSON に指定する function の中は、非同期に実行されます。
50回繰り返している $.getJSON ですが、その結果を処理する順番は呼び出した順番と同じとは限りません。
試しに、再生回数を処理している function の中で、結果として返ってきた videoid と viewCount をコンソールに出力してみてください。
for (var i=0; i<49; i++){ //全体を50回繰り返す(スタート行) //****動画IDごとに再生回数をゲット var url2 = "https://www.googleapis.com/youtube/v3/videos?id="+videoidArray[i]+"&key=" + apikey + "&part=statistics"; $.getJSON(url2, function(data) { // ★結果の videoid と再生回数をコンソールに出力 console.log(data.id, data.items[0].statistics.viewCount); var count= data.items[0].statistics.viewCount; //キーワードで検索した50個の動画のタイトルごとの再生回数を配列に入れる saiseikaisuuArray.push(count) }); //getJSON終わり } //全体を50回繰り返す(終わりの行)
この対応は、毎回一致していると思います。
ただ、出力される順番が違っているはず。
なので、別々の配列に入れた id と再生回数の並びが一致しないので、毎回違う、というふうに見えているのだと思います。
最初にキーワード検索した結果は、ひとつの item でオブジェクトを作り、videoid をキーにした連想配列に入れて、後で取得する再生回数も、videoid をキーにして、先の連想配列の結果とひもづける、というふうに処理した方が良いと思います。
# 具体的なコードを書いた方が良いかな?
ちょっとウソを書いてしまいました X-|
videos の返り値の video id が間違ってる。
// ★結果の videoid と再生回数をコンソールに出力 console.log(data.items[0].id, data.items[0].statistics.viewCount);
search の結果を回して、videos で取ってくるのをやってみました。
こんな感じです。
https://jsfiddle.net/08jagjw8/
早速有りがとうございます。今、連想配列のやり方を調べながらコードを考えていました。$.getJSON に指定する function が非同期に実行というのが理由だったのですね。動画IDで紐付ける考えが理解できました。
毎回IDと、再生回数が一致せず難儀していました。さっそく、jsfiddleのほうを試してみましたが、すごいです。このようなコードがすぐ書けるよう頑張って勉強します。これから少しづつ必要な箇所を追加して完成に近づけたいと思います。ありがとうございました。
a-kuma3さん
jsfiddleに作ってもらったコードについて教えて下さい。
videoIDと一致したところを抜き出すところがまだ理解できていません。
最初の item={videoTitle:**, channelTitle:**,channnelID:**,videoId:**}
のところは連想配列の中にそれぞれのデータを格納する。
次に、
list[item.videoId] = item
というのはlistという配列の中にvideoIdをキーにし連想配列を順番に入れているのでしょうか?
最後の↓のところも理解できませんでした。
$.getJSON(url, function(data) {
var videoid = data.items[0].id;
var item = list[videoid];
item.viewCount = data.items[0].statistics.viewCount;
これは、videoidをJSONから新たにゲットする。
その次のvar item = list[videoid]; はどういう処理でしょうか?
listの中からvideoidとマッチした箇所の連想配列をitemに入れる?
そしてvideoidとマッチしたところのview countをゲットしている??
最初の item={videoTitle:**, channelTitle:**,channnelID:**,videoId:**}
のところは連想配列の中にそれぞれのデータを格納する。
次に、
list[item.videoId] = item
というのはlistという配列の中にvideoIdをキーにし連想配列を順番に入れているのでしょうか?
「順番に」ではないです。「一度に」という方が近いです。
オブジェクトとして、search で拾ってこられるデータを格納して
item={videoTitle:**, channelTitle:**,channnelID:**,videoId:**}
そのオブジェクト(四つの情報を持った、ひとつのオブジェクト)を、連想配列 list に video id をキーにして格納してます。
list[item.videoId] = item
最後の↓のところも理解できませんでした。
$.getJSON(url, function(data) { var videoid = data.items[0].id; // (1) var item = list[videoid]; // (2) item.viewCount = data.items[0].statistics.viewCount; // (3)
(1) は、videos API の結果から、video id を取り出して、変数に入れてます。
url に指定したパラメータと同じもののはずなので、そちらを使うという手もありますが、非同期の処理なので、直近で手に入る値を使った方が、わけの分からない障害に悩むことが少ないです。
(2) は、search API で list に入れておいたデータのオブジェクトを取り出しています。
max までの件数が list に入っているはずですが、そのうちの video id が一致する一件だけです。
(3) は、(2) で取り出した一件分の動画データに、視聴回数のデータを入れてます。
これで、search API で取り出したチャンネルタイトルなどのデータと、videos API で取り出した視聴回数などのデータが、video id が一致しているひとつのオブジェクトに格納されたことになります。
a-kuma3さん、ありがとうございます。勉強になります。いろいろいじくって試してみました。
例えば、再生回数ではなく、動画IDに紐付いた関連動画数を表示させようとトライしています。
関連動画は
https://www.googleapis.com/youtube/v3/search?part=snippet&relatedToVideoId={動画ID}&type=video&key={API key}でゲットできるようです。
そこでコードを改造して以下のようにしたのですが、うまくいきません。
1つ1つ確認していくと関連動画数はうまくゲットできているようなのですが動画IDをマッチしていないのか?まったく表示されてきません。
原因はわかりますでしょうか。
var apikey = "・・・"; var inputkeyword = "サッカー"; var N = 10; var url = "https://www.googleapis.com/youtube/v3/search?key="+apikey+"&q="+inputkeyword+"&part=snippet&maxResults=" + N; var n_detail = 0; var n_done = 0; var list = []; var item =[]; // キーワードで検索 $.getJSON(url, function(data) { n_detail = data.items.length; for (var i = 0 ; i < data.items.length ; ++i) { var item = { videoTitle : data.items[i].snippet.title, channelTitle : data.items[i].snippet.channelTitle, channelId : data.items[i].snippet.channelId, videoId : data.items[i].id.videoId, }; list[ item.videoId ] = item; // video id で検索 var url1 = "https://www.googleapis.com/youtube/v3/search?part=snippet&relatedToVideoId="+item.videoId+"&type=video&key="+ apikey+""; $.getJSON(url1, function(data) { var videoid = data.items[0].id.videoId; var item = list[videoid]; item.totalResults = data.pageInfo.totalResults; n_done += 1; if (n_detail == n_done) { // 全て検索し終わったら、検索結果を表示 output_result(list); } }); } }); // 検索結果を表示 function output_result(list) { var s = "<tr>" + "<th>タイトル</th>" + "<th>チャンネル</th>" + "<th>チャンネルID</th>" + "<th>関連動画数</th>" + "</tr>"; for (var k in list) { var item = list[k]; s += "<tr>" + "<td>" + item.videoTitle + "</td>" + "<td>" + item.channelTitle + "</td>" + "<td>" + item.channelId + "</td>" + "<td>" + item.videoId + "</td>" + "<td>" + item.totalResults + "</td>" + "</tr>"; // console.log(list[k]); } var tbl = document.getElementById("result"); tbl.innerHTML = s; }
原因はわかりますでしょうか。
原因は、ここです。
var videoid = data.items[0].id.videoId;
内側の $.getJSON で返ってきた↑の videoId って、関連動画検索の元になった方の video id じゃなくて、関連してる結果の方の video id です。
最初に list[ item.videoId ] = item
で item を入れたときの video id じゃないので、内側の $.getJSON の
var item = list[videoid];
で、取ったつもりの item が空っぽなんです。
さて、どう直しますかねえ。
さて、どう直しますかねえ。
こんな感じでしょうか。
https://jsfiddle.net/950692vk/
内側の $.getJSON に指定する、検索語に動かす処理の渡し方を変更しました。
簡単に仕組みを説明するのは、ちょっと難しいのですが、「クロージャ」って言います。
a-kuma3さんありがとうございます。これは難しそうです。検索結果の連想配列からvideoIDを取り出して、普通に内側の$.getJSONをvar videoid = item.videoIdに変えただけではだめなんですね。試しにやってみたらうまくいきませんでした。
後の方に$.getJSON(url1, callback);とありますが、これがポイントなんですね。クロージャ調べながらじっくり理解してみます。
はい、難しいです。
ギアが 2段くらい上がります(個人的な感想)。
変数を介さずに書くと、こんな感じになります。
$.getJSON(url1, (function() { var videoid = item.videoId; return function(data) { var item = list[videoid]; item.totalResults = data.pageInfo.totalResults; n_done += 1; if (n_detail == n_done) { // 全て検索し終わったら、検索結果を表示 output_result(list); } }; })());
ね、訳が分からないでしょう :-)
肝になってるのは、この辺りです。
item.videoId = ...; // 外の世界の変数 var callback = (function() { // 関数を返す関数 var videoid = item.videoId; // 中の世界の変数にコピー return function(data) { var item = list[videoid]; // 中の世界の変数を関数に閉じ込める ... }; })(); // 関数を返す関数を実行してる
「クロージャ」という単語とともに「スコープチェーン」という単語を使って説明しているところが、きちんとした説明になっているはずです。
ですが、そのページは多分 難解。
理解の助けになるかどうかは分からないですが、「普通に内部の変数を変えてみたら、うまく行かなかった」のサンプルです。
var i, j; for (i = 0 ; i < 3 ; ++i) { var callback = function() { console.log("a:", i); } callback(); // すぐに呼んでみる setTimeout(callback, 0); // 非同期で呼んでみる } console.log("----------", i); for (j = 0 ; j < 3 ; ++j) { var callback = (function() { var jj = j; return function() { console.log("b:", jj); } })(); callback(); // すぐに呼んでみる setTimeout(callback, 0); // 非同期で呼んでみる } console.log("==========", j); console.log("==========", jj); // エラーになります
setTimeout というのは、指定した処理をある時間が経った後に実行します。
タイミング的には、$.getJSON の非同期処理と同じような動作をします。
で、先のサンプルを動かすと、ブラウザのコンソールには以下のような感じで出力されるはずです。
a: 0 # ループの中で呼ぶと、0、1、2 と表示される a: 1 a: 2 ---------- 3 # ひとつめのループが終了 # ループが終わると、i は 3 になっている b: 0 # ふたつめのループでも同じ b: 1 b: 2 ========== 3 # ふたつめのループが終了 # まだ、setTimeout に指定した処理は動かない a: 3 # 最初のループの setTimeout # ループは終わっているので、i = 3 が 3 回表示される a: 3 a: 3 b: 0 # ふたつ目のループの setTimeout # ループの中で関数に閉じ込めた数字が出力される b: 1 b: 2 ReferenceError: jj is not defined # 関数の中で宣言された jj は、外では使えない
とても複雑です!(*^^*) もう1つ教えて下さい。最初のキーワードから動画を50個探してくるところで、試しに日付順にデータを取ってくるオプションをいれてみたのですが、うまくいきませんでした。
(URLに order=date を追加)
デフォルトの関連性の高い順番ではなく日付順になるだけなので何ら問題ないと思ったのですが動作しません。ためしに内側の$.getJSONのほうのURLにも日付順にしてみたのですがこちらはvideoIdとマッチしたデータをゲットするだけなので関係ないですよね? 何が原因なのでしょうか。
var inputkeyword = "サッカー"; var N = 10; var url = "https://www.googleapis.com/youtube/v3/search?key="+apikey+"&q="+inputkeyword+"&part=snippet&order=date&maxResults=" + N;
デフォルトの関連性の高い順番ではなく日付順になるだけなので何ら問題ないと思ったのですが動作しません。ためしに内側の$.getJSONのほうのURLにも日付順にしてみたのですがこちらはvideoIdとマッチしたデータをゲットするだけなので関係ないですよね? 何が原因なのでしょうか。
例えば、サッカーで order=date を指定して検索すると、6番目からデータが変わってます。
5番目は
data.items[4].id.kind : "youtube#video" data.items[4].id.videoId : "I_GxZc1RekA"
なのですが、6番目が
data.items[5].id.kind : "youtube#playlist" data.items[5].id.playlistId : "PLc4IAowg0iRAuITaOWa5_qCl0859b5OxM"
となっています。
videoId ではなく、playlistId が入っているために、内側の関連動画検索には relatedToVideoId=undefined を渡して検索しているために、API の応答がエラーになって返ります。
外側の search API で type=video も指定して、動画だけにすると大丈夫です。
→ Search: list | YouTube Data API (v3) | Google Developers
なるほど、それが原因だったのですね。Developersマニュアルで確認しました。これを使いこなしたらいろいろな情報が取れてとてもおもしろいです。JSONのデータの結果を表示させる方法などとても勉強になりました。ありがとうございます。
コメントはありません