Python

pythonでYouTubeの再生数が指定回数以上の動画タイトルを取得

概要

人気のYoutube動画タイトルのデータセットを作ろうしたら意外と苦戦したので備忘録として.
全動画から検索はできなさそうだったので,人気YouTuberのチャンネルidを地道に手作業で集めて,各チャンネルに紐づく動画で再生数が多いもののみを取得しています.

タイトル取得手順

YouTube Data API(v3)を用います.
指定再生数以上の動画リストをまるっと返してくれるような都合の良いリクエスト方法はないようで,以下のよう手順を踏んでいます.

  1. 人気のあるチャンネルのid収集(手作業)
  2. 各動画チャンネルに紐づく動画リストを取得
  3. 各動画の再生数を取得
  4. 再生数が指定回数以上ならタイトルを保存

取得部分の関数はこんな感じ.

def getVideoTitle(ch, term_start, term_end, next):
  # チャンネルの指定期間内の動画一覧を取得
  request = urllib.urlopen("https://www.googleapis.com/youtube/v3/search?channelId=" + ch + "&part=id,snippet" + term_start + term_end + "&maxResults=50&key=***your api key***" + next)
  response = request.read()  # 文字列が返ってくる
  data = json.loads(response) #文字列をjson化

  id_list = []
  title_list = []
  for d in data["items"]:
    if "videoId" in d["id"]:
      id_list.append(d["id"]["videoId"])
      title_list.append(d["snippet"]["title"])

  videoid = "&id=" + ','.join(id_list)
  titles = []
  if len(id_list) > 0:
    # 取得した動画の再生数を取得し判定後,タイトルリストに追加
    request = urllib.urlopen("https://www.googleapis.com/youtube/v3/videos?part=statistics" + videoid + "&fields=items(statistics)&key=***your api key***")
    response = request.read()
    count = 0
    for item in json.loads(response)["items"]:
      if int(item["statistics"]["viewCount"]) > 1000000:  # 任意の再生数を指定
        titles.append(title_list[count])
      count += 1

  if "nextPageToken" in data["items"]:
    npt = data["nextPageToken"]
  else:
    npt = ""

  return [npt, titles]

チャンネルに紐づく動画情報には再生数がなく,取得したvideoIdで再リクエストして再生数含む動画情報を取得しています.

途中で動画情報が取得できなくなる

過去に他の方が同じ問題に直面していたようで,そちらを参考にしました.
YouTubeの特定のチャンネルに紐付く動画を取得する。(YouTube Data API (v3) Search)
一定期間ごとに分けて繰り返し動画リストを取得することで解消できます.先ほどのコードでstart_termend_termを引数に与えていたのはこのためです.

以下のように,先ほどの関数を取得期間をずらしながら繰り返し呼びタイトルを取得しました.

pageToken = "&pageToken="
TitleList = []
for i in range(36):
  before = "&publishedBefore=" + date.strftime("%Y-%m-%d") + time
  date = date - datetime.timedelta(weeks=4)
  after = "&publishedAfter=" + date.strftime("%Y-%m-%d") + time
  next = ""
  while next != pageToken:
    next, titles = getVideoTitle(ch, after, before, next)
    next = pageToken + next
    TitleList.extend(titles)