C#でYouTubeの動画の情報を取得します。キーワードや日時を指定し、評価や再生数の高い順に並べてcvsファイルで出力させてみましょう。
YouTube APIを利用するには「APIキー」が必須です。APIキーを持っていない方は取得しておきましょう。以下のサイトの説明がわかりやすいです。「YouTube Data API v3」を利用します。
googleアカウントの取得方法とYouTube APIの設定 | DIYプログラミング
https://www.googleapis.com/youtube/v3/search
必須パラメータ part
string
APIレスポンスに含める 1 つまたは複数の search リソースのプロパティをカンマ区切りリストの形式で指定します。このパラメータに指定できる part 名は id と snippet です。
動画の情報を集めたいとすればあるキーワードで検索して再生回数が多い動画ではないでしょうか? あと特定の期間において再生数が多い動画というのは調査対象になるのではないでしょうか?
必須パラメータ partのほかにもいろいろありますが、ここで使うのは以下のものです。
q
string
検索クエリを指定します。
order
date リソースを作成日の新しい順に並べます。
rating リソースを評価の高い順に並べます。
relevance リソースを検索クエリの関連性が高い順に並べます。このパラメータのデフォルト値です。
title リソースをタイトルのアルファベット順に並べます。
videoCount アップロード動画の番号順(降順)にチャンネルを並べます。
viewCount リソースを再生回数の多い順に並べます。
maxResults
unsigned integer
maxResults パラメータには、結果セットとして返されるアイテムの最大数を指定します。0 以上 50 以下の値を指定できます。デフォルト値は 5 です。
type
string
type パラメータは、検索クエリの対象を特定のタイプのリソースのみに制限します。値はカンマで区切られたリソースのタイプのリストです。channel、playlist、videoを指定できます。デフォルト値は video,channel,playlist です。
publishedAfter
publishedBefore
datetime
publishedAfterは指定した日時より後に作成されたリソースのみ、publishedBeforeは指定した日時より前に作成されたリソースのみが API レスポンスに含まれるように指定します。この値は RFC 3339 形式の date-time 値です(1970-01-01T00:00:00Z)。
ということで
https://www.googleapis.com/youtube/v3/search?
q=<検索したい文字列>
&key=<取得したキー>
&part=snippet
&order=viewCount
&maxResults=<何件取得するか>
&type=video
&publishedAfter=<開始日時>
&publishedBefore=<終了日時>
をすべてつなぎ合わせたものを使えばデータを取得できることがわかります。実際の再生回数はここでは取得できないので、この処理で取得したデータをつかって調べることになります。
以下のようなコードでVideoIdを取得する方法を考えます。
1 2 3 4 5 6 7 8 9 10 |
// 「プログラミング」で検索 視聴回数が多い順 2020, 1, 1から8, 1まで DateTime after = new DateTime(2020, 1, 1); DateTime before = new DateTime(2020, 8, 1); string text = GetResponseText("プログラミング", 5, after, before, Order.viewCount); List<string> vs = GetVideoIdFromResText(text); foreach(string str in vs) { // str が VideoId } |
1 2 3 4 5 6 7 |
enum Order { date, //リソースを作成日の新しい順に並べます。 rating, // リソースを評価の高い順に並べます。 relevance, // リソースを検索クエリの関連性が高い順に並べます。このパラメータのデフォルト値です。 viewCount, // リソースを再生回数の多い順に並べます。 } |
キーワードと日時、何の順で何件取得するか。これを決めればGetResponseTextメソッドでレスポンスを取得することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
public partial class Form1 : Form { string GetResponseText(string keyWord, int count, DateTime after, DateTime before, Order order) { string afterString = ""; string beforeString = ""; if(after != DateTime.MinValue) afterString = after.ToString("yyyy-MM-ddT00:00:00Z"); if(before != DateTime.MinValue) beforeString = before.ToString("yyyy-MM-ddT00:00:00Z"); System.Text.Encoding enc = System.Text.Encoding.UTF8; string urlEnc = System.Web.HttpUtility.UrlEncode(keyWord, enc); //date リソースを作成日の新しい順に並べます。 //rating リソースを評価の高い順に並べます。 //relevance リソースを検索クエリの関連性が高い順に並べます。このパラメータのデフォルト値です。 //viewCount リソースを再生回数の多い順に並べます。 string url = ""; url += "https://www.googleapis.com/youtube/v3/search?q="; url += urlEnc; url += "&key="; url += myKey; url += "&part=id"; if(order == Order.date) url += "&order=date"; else if(order == Order.rating) url += "&order=rating"; else if(order == Order.viewCount) url += "&order=viewCount"; else url += "&order=relevance"; if(count > 50) count = 50; if(count < 1) count = 1; url += "&maxResults=" + count.ToString(); if(afterString != "") url += "&publishedAfter=" + afterString; if(beforeString != "") url += "&publishedBefore=" + beforeString; url += "&prettyPrint=true"; url += "&type=video"; HttpWebRequest httpWebRequest = WebRequest.CreateHttp(url); HttpWebResponse res = (HttpWebResponse)httpWebRequest.GetResponse(); Stream stream = res.GetResponseStream(); StreamReader sr = new StreamReader(stream); string str = sr.ReadToEnd(); sr.Close(); return str; } List<string> GetVideoIdFromResText(string str) { // 改行で分割して "videoId" がある行を調べれば videoId がわかる string[] vs1 = str.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries); List<string> list = vs1.Where(x => x.IndexOf("\"videoId\"") != -1).ToList(); List<string> ret = new List<string>(); foreach(string str1 in list) { string str2 = str1.Replace("\"videoId\"", ""); str2 = str2.Replace(" ", ""); str2 = str2.Replace(",", ""); string[] ss = str2.Split(new string[] { "\"" }, StringSplitOptions.RemoveEmptyEntries); string id = ss[ss.Length - 1]; ret.Add(id); } return ret; } } |
ではVideoIdから動画の情報を得るにはどうすればいいでしょうか?
https://www.googleapis.com/youtube/v3/videos
snippet
タイトル、説明、カテゴリなどの動画の基本的な情報
statistics
動画に関する統計情報
ここでは以下をつなぎ合わせてデータを取得します。
https://www.googleapis.com/youtube/v3/videos?
&key=<取得したキー>
&part=snippet,statistics
&id=<VideoId>
&fields=
items/snippet/title, // 動画のタイトル
items/snippet/description, // 動画の概要
items/snippet/publishedAt, // 動画がアップロードされた日時
items/snippet/channelTitle, // チャンネルのタイトル
items/statistics/viewCount, // 視聴回数
items/statistics/likeCount // 「高く評価」の数
&prettyPrint=true
1 2 3 4 5 6 7 8 9 10 |
class Data { public string title = ""; public string description = ""; public string veiwCount = ""; public string url = ""; public string publishedAt = ""; public string channelTitle = ""; public string likeCount = ""; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
public partial class Form1 : Form { Data GetDataFromVideoId(string id) { string url = ""; url += "https://www.googleapis.com/youtube/v3/videos?id="; url += id; url += "&key="; url += myKey; url += "&part=snippet,statistics"; url += "&fields="; url += "items/snippet/title,"; // 動画のタイトル url += "items/snippet/description,"; // 動画の概要 url += "items/snippet/publishedAt,"; // 動画がアップロードされた日時 url += "items/snippet/channelTitle,"; // チャンネルのタイトル url += "items/statistics/viewCount,"; // 視聴回数 url += "items/statistics/likeCount"; // 「高く評価」の数 url += "&prettyPrint=true"; HttpWebRequest httpWebRequest = HttpWebRequest.CreateHttp(url); HttpWebResponse res = (HttpWebResponse)httpWebRequest.GetResponse(); Stream strem = res.GetResponseStream(); StreamReader sr = new StreamReader(strem); string s = sr.ReadToEnd(); sr.Close(); richTextBox1.Text = s; string[] vs1 = s.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries); Data data = new Data(); // 動画のタイトル { string str = vs1.FirstOrDefault(x => x.IndexOf("\"title\"") != -1); str = str.Replace(",", ""); str = str.Replace(" ", ""); string[] ss = str.Split(new string[] { "\"" }, StringSplitOptions.RemoveEmptyEntries); string title = ss[ss.Length - 1]; data.title = title; } // 動画の概要 { string str = vs1.FirstOrDefault(x => x.IndexOf("\"description\"") != -1); if(str != "") { str = str.Replace(",", ""); str = str.Replace(" ", ""); string[] ss = str.Split(new string[] { "\"" }, StringSplitOptions.RemoveEmptyEntries); string description = ss[ss.Length - 1]; data.description = description; } } // 動画がアップロードされた日時 { string str = vs1.FirstOrDefault(x => x.IndexOf("\"publishedAt\"") != -1); if(str != "") { str = str.Replace(",", ""); str = str.Replace(" ", ""); string[] ss = str.Split(new string[] { "\"" }, StringSplitOptions.RemoveEmptyEntries); string publishedAt = ss[ss.Length - 1]; data.publishedAt = publishedAt; } } // チャンネルのタイトル { string str = vs1.FirstOrDefault(x => x.IndexOf("\"channelTitle\"") != -1); if(str != "") { str = str.Replace(",", ""); str = str.Replace(" ", ""); string[] ss = str.Split(new string[] { "\"" }, StringSplitOptions.RemoveEmptyEntries); string channelTitle = ss[ss.Length - 1]; data.channelTitle = channelTitle; } } // 「高く評価」の数 { string str = vs1.FirstOrDefault(x => x.IndexOf("\"likeCount\"") != -1); if(str != "") { str = str.Replace(",", ""); str = str.Replace(" ", ""); string[] ss = str.Split(new string[] { "\"" }, StringSplitOptions.RemoveEmptyEntries); string likeCount = ss[ss.Length - 1]; data.likeCount = likeCount; } } // 視聴回数 { string str = vs1.FirstOrDefault(x => x.IndexOf("\"viewCount\"") != -1); if(str != "") { str = str.Replace(",", ""); str = str.Replace(" ", ""); string[] ss = str.Split(new string[] { "\"" }, StringSplitOptions.RemoveEmptyEntries); string veiwCount = ss[ss.Length - 1]; data.veiwCount = veiwCount; } } data.url = "https://www.youtube.com/watch?v=" + id; return data; } } |
チェックボックスで取得するかどうかを変更できるようにします。
1 2 3 4 5 6 7 8 9 10 11 12 |
public partial class Form1 : Form { private void checkBox1_CheckedChanged(object sender, EventArgs e) { DateTimePickerAfter.Enabled = checkBox1.Checked; } private void checkBox2_CheckedChanged(object sender, EventArgs e) { DateTimePickerBefore.Enabled = checkBox2.Checked; } } |
[取得]ボタンがクリックされたら・・・
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
public partial class Form1 : Form { private void Button1_Click(object sender, EventArgs e) { if(TextBoxKeyWord.Text == "") { return; } SaveFileDialog save = new SaveFileDialog(); save.Title = "CSVファイルとして保存する"; save.Filter = "CSVファイル(*.csv)|*.csv"; if(save.ShowDialog() != DialogResult.OK) return; string filePath = save.FileName; save.Dispose(); DateTime after = DateTimePickerAfter.Value; DateTime before = DateTimePickerBefore.Value; if(!DateTimePickerAfter.Enabled) after = DateTime.MinValue; if(!DateTimePickerBefore.Enabled) before = DateTime.MinValue; //ComboBox1.Items.Add("関連性が高い順"); //ComboBox1.Items.Add("新しい順"); //ComboBox1.Items.Add("評価の高い順"); //ComboBox1.Items.Add("再生回数"); Order order; if(ComboBox1.SelectedIndex == 1) order = Order.date; else if(ComboBox1.SelectedIndex == 2) order = Order.rating; else if(ComboBox1.SelectedIndex == 3) order = Order.viewCount; else order = Order.relevance; string text = GetResponseText(TextBoxKeyWord.Text, (int)numericUpDown1.Value, after, before, order); List<string> vs = GetVideoIdFromResText(text); List<Data> datas = new List<Data>(); foreach(string id in vs) { Data data = GetDataFromVideoId(id); datas.Add(data); } StringBuilder sb = new StringBuilder(); string str0 = "url,タイトル,アップロードされた日,視聴回数,高い評価の数,概要,チャンネル名\n"; sb.Append(str0); foreach(Data data in datas) { string str = String.Format("\"{0}\",\"{1}\",\"{2}\",\"{3}\",\"{4}\",\"{5}\",\"{6}\"\n", data.url, data.title, data.publishedAt, IntString(data.veiwCount), IntString(data.likeCount), data.description, data.channelTitle ); sb.Append(str); } StreamWriter sw = new StreamWriter(filePath, false, Encoding.Default); sw.Write(sb.ToString()); sw.Close(); if(CheckBoxOpenFile.Checked) { if(File.Exists(filePath)) System.Diagnostics.Process.Start(filePath); } else { MessageBox.Show("保存しました"); } } string IntString(string str) { int i = int.Parse(str); return i.ToString("#,0"); } } |