YouTube Data APIを使って登録者の少ないYouTubeチャンネルを探す
YouTubeからデータを取得しまくってアプリケーションを作ろうと思っていたが、一日あたりにリクエストできる量が限られていて結構厳しくて頓挫した。 アプリケーションを作る前にやりたいことができるのか確かめるためにスクリプトを書いたので、供養のために記事にしておく。
背景
いわゆる底辺Youtuberを見つけて応援したかった。 しかしながら、彼らを効率的に探す方法が見当たらなかった。
頑張って人力で探す方法は下記ページにまとめられている。
底辺ユーチューバー 探し方4選 見つけ方 YouTuber 登録数が少ない | 知恵袋wikiまとめ
そこで、YouTubeのAPIを使うことで、効率的に底辺YouTuberを見つけることができないか試した。
やりたいこと
底辺YouTuberには明確な定義がないので、探す対象を「登録者が少ないが、活発に活動しているYouTubeチャンネル」とした。
「登録者が少ないが、活発に活動しているYouTubeチャンネル」を、仮に次のように定義した。
- 登録者が1万人以下
- 直近一ヶ月の動画投稿数が15本以上
YouTube Data API
YouTube Data APIは、Youtubeが公式に提供しているAPI群。 情報収集や分析に必要なAPIは一通り揃っている。
API Reference | YouTube Data API | Google Developers
利用制限
GCPのアカウントがあれば誰でも利用できる。クォータと呼ばれる利用上限を設けている。クエリごとに消費するクォータが異なるが、ざっくりいうと多くの情報を取得するほどクォータを消費する。
YouTube Data APIのクォータ数増加申請が通った件の振り返り - Qiita
クォータは、GCPのコンソールの「IAMと管理」→「割当て」から確認できる。
取得方法の設計
次の手順で、「登録者が1万人以下かつ直近一ヶ月の動画投稿数が15本以上チャンネルのリスト」を得る。
Search: list APIを用いて、すべてのチャンネルのIDを得る https://developers.google.com/youtube/v3/docs/search/list
Channels: list APIを用いて、1. で得たチャンネルの登録者数とアップロード動画リストのIDを取得する Channels: list | YouTube Data API | Google Developers
2で得た登録者数を用いて1のチャンネルリストを登録者数1万人以下のものに絞り込む
3で得たチャンネルのアップロード動画リストIDを用いて、アップロード動画を取得する
4で得たアップロード動画リストを用いて、一ヶ月の動画投稿数が15本以上のチャンネルを絞り込む
結論から言うと、この設計ではうまく行かない。1のチャンネルの取得の時点で、簡単に利用制限に引っかかってしまう。このため、APIリクエストの少ない別の方法が必要になる。
2まで作ってうまく行かないことに気がついたので、次節移行に、以下に2までをrubyで実行する方法を示す。
下準備
YouTube Data APIを使う前に、下記の準備が必要。
こちらのページに詳しく記載されている。
APIを色々たたいて実験したかったのでAPIドキュメントをよみつつpostman を利用した。 postmanの利用でもクォータは消費されるので注意する。
Search: list APIを用いて、すべてのチャンネルのIDを得る
API通信にfaradayを使いたいのでインストールしておく。
gem install faraday faraday_middleware
search: list APIを利用して、チャンネルを50件ずつ取得する。
- 本来は取得できる全量を取得したいが6×50で300件としておく。
- next_page_tokenを使ってページネーションするので、取得結果とセットで同じオブジェクトにまとめる
require 'faraday' require 'faraday_middleware' class ChannelResult attr_reader :channels, :next_page_token def initialize(channels, next_page_token) @channels = channels @next_page_token = next_page_token end end def fetch_channels(next_page_token = nil) url = "https://www.googleapis.com/youtube/v3/search?part=id&type=channel&maxResults=50®ionCode=JP&key=#{API_KEY}" conn = Faraday.new(url: url) { |faraday| faraday.adapter Faraday.default_adapter faraday.response :json } response = conn.get(nil, "pageToken" => next_page_token) pp response.body channels = response.body["items"].map { _1["id"]["channelId"] } next_page_token = response.body["nextPageToken"] ChannelResult.new(channels, next_page_token) end def channels t = nil (1..6).flat_map do resp = fetch_channels(t) t = resp.next_page_token resp end end puts channels
Channels: list APIを用いて、チャンネルの登録者数を取得する
- idを指定することで、まとめて50件取得できる
- レスポンスの構造はドキュメントを見て把握する
class ChannelDetail attr_reader :id, :subscribers, :title def initialize(id, subscribers, title) @id = id @subscribers = subscribers @title = title end def format "#{title} #{subscribers}" end end def channel_details(list) ids = list.channels.join(",") url = "https://www.googleapis.com/youtube/v3/channels?part=statistics,snippet&id=#{ids}&key=#{API_KEY}" conn = Faraday.new(url: url) { |faraday| faraday.adapter Faraday.default_adapter faraday.response :json } response = conn.get response.body["items"].map do ChannelDetail.new( _1["id"], _1["statistics"]["subscriberCount"], _1["snippet"]["title"] ) end end def ch(channel_lists) channel_lists.flat_map do |list| channel_details(list) end end details = ch(channels) sorted = details.sort_by do _1.subscribers.to_i end
実行すると、こんなかんじでランキング形式でチャンネルと登録者数を得られる
コード全量
問題点
API呼び出しとデータ取得の量が多すぎるため、一瞬でクォータの上限に達する。
今後
少ないAPI呼び出して所望のチャンネルを得られるような工夫をする。 searchの時点である程度絞れるようにするとよさそう。