PythonでYouTube Data APIを利用して再生リストを操作した [忘備録]

やったこと

YouTube Data APIを用いて、ヤマトイオリが公開している動画全てを自前の再生リストに追加

動機(読まなくていい)

YouTubeでは、チャンネルの動画タブから[全て再生]をクリックすると必ず新しい順になってしまうため古い動画から見ることができない
解決方法として、自前でマイリストを作成すると古い順に並び替えることができる

が、投稿された動画を全てリストに追加するといった操作も見つけられなかっため、150本近くある動画を一つずつ追加せざるを得なくなった
あほくさ

お品書き

  • Google Console関係
    • API Keyの発行
    • OAuthの発行 など
  • Python関係
    • APIキーを利用して、チャンネル情報やら動画情報を取得
    • OAuth2で認証して再生リストへ追加

Google Console

登録

YouTube Data API の概要  |  Google Developers 上のページを参考にやれば大抵なんとかなる

初めての利用の場合、プロジェクト名を入力するよう求められるので、適当に入力
左ペインのライブラリから、YouTube Data APIを探して有効化

APIキー

左ペインの認証情報から、最上段検索ボックスすぐ下の認証情報を作成をクリック(ひょっとすると画面違うかも)
APIキーをクリックして設定
アプリケーションの制限欄でIPアドレスの制限かけようとしたけど、うまく行かなかったので解除した
その代わり、APIの制限でYouTube Data APIだけにしといた 念の為程度
APIはこれで設定完了

OAuth

よくわかってない
とりあえず左ペインのOAuth同意画面の作成からプロジェクト名を入力
スコープを追加からYouTubeを選ぶ
他にもURLやら入力する欄あるけどなくても動いたので
保存ボタンを押す
プライベートなスコープがどうのこうので確認ステータスがどうのこうのって言われるが、無視してもOKっぽい
多分開発して公開する人用? 個人利用なら無視してもセキュリティ的な問題はなさそう
認証時の警告画面がでるだけだと思う

左ペインの認証情報から認証情報を作成→その他のアプリケーションでなんとかなった
クライアント情報の右端にあるダウンロードボタンを押してjsonをダウンロードしておく。後で使うので
末尾によくわからんの付いてるし、client_secrets.jsonとかにしとけばよさそう

登録終わりは記憶にある限りではこれだけ

Python

リファレンスの読み解き方

API Reference  |  YouTube Data API  |  Google Developers
これが最初うまくつかめずにに苦労した

概要

まず、概要を見る。(チャンネル Channelsあたりがわかりやすそう)
最初に見えるのがメソッド。このタイミングでクリックすると嵌る(ハマった)
大事なのがリソース表現と、プロパティ
Snippetだとこんな情報がありますよ~とか書いてあるのだが、この情報をメソッドで利用する。特にlist
これを知らずにメソッドを先に見てしまうと、Snippetってなんだよってなる(なった)

メソッド

HTTP リクエス

GETとかPOSTとかで叩くURLが乗っている
requests.getなのかrequests.postなのかわかる
あとで解説します

パラメータ

paramsで指定するデータ
必須なのはpart
このページに書かれているpartで指定できるStringこそ、概要にあったプロパティ
partでプロパティを指定すると、概要に書いてあったプロパティの情報が取得できる

フィルタと省略可能なパラメーターは日本語が読めれば使えるはず
使用例は次の項目から

Channelsの使い方

contentDetails.relatedPlaylists.uploadsで動画一覧を取得するために利用

param = {
  'key': APIキー,
  'part': 'contentDetails',
  'id': チャンネルID
}

URLパラメータはこんな感じ
APIキーは、先程Google Consoleで取ったやつ
IDは、取得したいチャンネルURLの
channel/hogehoge の部分
ヤマトイオリなら UCyb-cllCkMREr9de-hoiDrg なので
'id': 'UCyb-cllCkMREr9de-hoiDrg'
となる

あとは
requests.get('https://www.googleapis.com/youtube/v3/channels', params=param).json()
でレスポンスが帰ってくる

.jsonをつけることでdicデータとして取得できる

playlistItemsの使い方(list編)

動画一覧を取得するために利用

param = {
  'key': APIキー,
  'part': 'snippet',
  'playlistId': プレイリストID,
  'maxResults': '50'
}

プレイリストIDとは、前述のcontentDetails.relatedPlaylists.uploadsで取得できるやつ
これを指定することで、アップロードされている全ての動画が取得できる。なんでだろう?
maxResultは、初期が5なので特に問題がなければ50のほうがよさそう

ただし、50でも足りないことのほうが多いと思うので、そういうときはnextPageTokenを利用する

resource_id_list = []
while True:
    get_movie_info = requests.get('https://www.googleapis.com/youtube/v3/playlistItems', params=param).json()
    # print(json.dumps(hoge['items'], indent='\t', ensure_ascii=False))
    for i in get_movie_info['items']:
        print(i['snippet']['title'], ':', i['snippet']['resourceId'])
        resource_id_list.append(i['snippet']['resourceId'])
    try:
        next_page_token = get_movie_info['nextPageToken']
    except KeyError:
        break
    param['pageToken'] = next_page_token

こんな感じで使った
コードが汚いのはご愛嬌

これで投稿された動画全てのIDが取得できる

playlistItemsの使い方(insert編)

Playlists: insert  |  YouTube Data API  |  Google Developers このサンプルコードを参考に、OAuth2を実装
コピペで動く
先程ダウンロードしたOAuth2のjsonはここで必要だったのだ
MISSING_CLIENT_SECRETS_MESSAGEとyoutube = の下りはひょっとしたらいらないかも 検証していない

コードを実行すると、プログラム名-oauth2.jsonなるものができていると思うので、中を確認してアクセストークンが生成されていればOK

さて、 PlaylistItems: insert  |  YouTube Data API  |  Google Developers を見ると、パラメータの本文なるものが指定されている。
また、今回は認証情報を乗せる必要があるし、従来どおりpartも必須となっている。 今までと違い、requestsに乗せるものが多くなるので、答えを書くと

headers = {
    'Authorization': 'Bearer ' + アクセストークン
}

param = {
    'part': 'snippet'
}

data = {
    'snippet': {
        'playlistId': プレイリストID,
        'resourceId': リソースID
    }
}

requests.post('https://www.googleapis.com/youtube/v3/playlistItems',
                params=param,
                json=data,
                headers=headers)

こう
本来アクセストークンの直書きはセキュリティ的に怪しいかもだけど、自家製なのでヨシ!
アクセストークンは、プログラム名-oauth2.jsonから取得
プレイリストIDは、自分で作成したプレイリストの?list=hogehoge
リソースIDは、IDと謳っておきながらjson形式で渡す必要がある。
具体的には、resource_id_listに入っているような、kindとvideoIdとのセットである
コード的にはこう

for i in resource_id_list:
    data = {
        'snippet': {
            'playlistId': 'プレイリストID',
            'resourceId': i
        }
    }
    requests.post('https://www.googleapis.com/youtube/v3/playlistItems',
                    params=param,
                    json=data,
                    headers=headers)
    print('END: ', i)
    sleep(5)

sleepが入っているのはスクレイピングのときの癖なので、なくてもいいと思う

以上!

あとで読んだときにちゃんと理解できると良いなぁ

参考文献

YouTube Data API の概要  |  Google Developers

Youtube API V3でユーザーがアップロードした動画リストを取得する方法 [無料ホームページ作成クラウドサービス まめわざ]

Quickstart — Requests 2.22.0 documentation