下記の手順で、検証してみました。
1.実投稿動画数の確認
YouTubeはスクレイピング(結果として表示されるHTMLページをseleniumその他プログラムの自動的な手段を用いて取得すること)が禁止されている。
したがって、スクレイピング(類似の動作含む)を回避しつつ、動画の数を効率よく数えるため、下記の要領で実投稿動画数をカウントした。
Windows 10 Professional バージョン20H2
ブラウザソフトは、Microsoft Edge バージョン 88.0.705.50 (公式ビルド) (64 ビット)で、
拡張機能をすべて無効にして行った。
(下記のうちブラウザ操作についてはスクリプト等の機械的手段を行わずすべて手動で行った)
・ブラウザでYouTubeからログオフする。
・当該チャンネルページに飛ぶ。
・ブラウザの設定(サイトのアクセス許可)で、「イメージ」を「ブロック」し、画像をオフにする。
・チャンネルページで、動画タブを開く。
・「アップロード済み」となっているセレクトボックスを「すべての動画」に変える。
・中断に「すべて表示」のリンクがあるので、それをクリックする。
・ページをスクロールし、すべての投稿動画をブラウザ内に表示させる。
・ページ内の動画欄をドラッグし、Ctrl+Cを押して、テキスト情報をクリップボードにコピーする。
・Excelを立ち上げ、クリップボードにコピーした内容を、テキスト形式で張り付ける。
・Excel上で、気力で動画タイトルの行のみ抽出する。「字幕」という文字があったり「360°~」から始まるタイトルが2行になっていたりしたので手間取った
以上により、2021/1/25 22:18JST時点で、のチャンネルページに「すべての動画」として表示される動画は
**「440個」**であることが確認できました。
2.YouTube APIで取得できる動画数の確認
# 質問文のスクリプトで取得できる結果から、videoidとタイトルのリストを作る。
videos = []
add = videos.append
for i in Search_Video:
for t in i["items"]:
if t["id"].get("videoId"):
add((t["id"]["videoId"], t["snippet"]["title"]))
>>> len(videos)
>>> 412
となり、2021/1/25 22:35JST時点で同チャンネルからAPIで取得できる動画の数は
**「412個」**であることが分かりました。
APIで取得したタイトルと、エクセルのタイトルを昇順並び替えして照合し、どの動画が欠落しているか確認しました。
APIにあって、エクセルにはないものが1件(なんたらフリーチャット)、
エクセル(実投稿動画)にあって、APIにはないものが29件確認できました。
3.考察
APIで取得できていなかった29件の動画IDは以下です。
{'KKXv11Yah4Q', 'aVum3p02SAs', 'hCNqq6axQtY', '_eQHVri4ieo', 'xqkuRNaMXjM', '8dtqh0gxBeQ', 'LRDS84JooTo', 'xq7BDlPc3CY', 'w0pv9F4_lYs', 'naHTMKnEjsM', 'mhhnWObC-uA', 'ojAPlue629o', 'tiSt4O-nppM',
'OFELMaAYfjE', 'EnzRIkWBNeM', 'Z9iXsDO-xl0', 'vlvwH53NCUg', '0QbD-TjW4GE', 'Sj7YcB1TlI0', 'quuZ06TLy-E', 'SpSoY0vvc1c', '6ezHwI9W3YU', 'YYLJpD_V1aQ', 'MbG5iQzXYvw', 'V2PuidDn6GI', 'trGGp3zbJoA', 'Bw_uE7JAFlg', 'a0XhjXcJBm0', 'PFm6cps37oY'}
これらの動画について、APIで取得できる動画情報その他からは、取得できている動画との差異を見つけることはできませんでした。
YouTube search.listで取得できない動画IDが存在するのは、おそらくYouTube APIのバグではないかと思われます。
4.抜け漏れの回避方法
1つの方法として、playlistを使用する手段が考えられます。(ただし確実に抜け漏れを防げるかどうかは検証しきれていません)
「UU」にチャンネルIDの3文字目以降をつなげた文字列が、そのチャンネルのアップロード済み動画一覧を取得できるプレイリストIDになっているようです。
(配信中の動画や、永続的に待機状態になっている動画は取得できません。)
完全に一致しているかは検証できていません。
質問中に記載されたチャンネルに関して、下記のスクリプトで取得できる動画数と、目視で数えた投稿動画数は、一致しました。(2021/1/25 0:26JST時点。数のみ確認したため、入り繰りがある可能性はゼロではありません。)
import requests
def get_playlist_items(pl_id):
api_key='api_key'
url = f'https://www.googleapis.com/youtube/v3/playlistItems?playlistId={"UU"+pl_id[2:]}&key={api_key}&part=snippet&maxResults=50'
ret = []
while True:
try:
resp = requests.get(url)
resp.raise_for_status()
data = resp.json()
except Exception as e:
print(str(e))
return []
items = data.get('items')
if items:
ret.extend(items)
nextPageToken = data.get('nextPageToken')
if nextPageToken:
url=f'https://www.googleapis.com/youtube/v3/playlistItems?playlistId={"UU"+pl_id[2:]}&key={api_key}&part=snippet&maxResults=50&pageToken={nextPageToken}'
else:
return ret
# テスト
items = get_playlist_items("UCD-miitqNY3nyukJ4Fnf4_A")
for v in items:
print(v["snippet"]["resourceId"]["videoId"], v["snippet"]["title"])
print(len(items))