この記事では、YouTube Data API v3を使って、指定したチャンネルの動画一覧を取得し、CSVに保存する方法をまとめます。
チャンネルの動画一覧を取得する方法はいくつかありますが、この記事では channels.list でアップロード用再生リストIDを取得し、playlistItems.list で動画一覧をたどる方法を使います。検索APIを使うより意図が明確で、クォータも抑えやすいです。
取得対象は、YouTube Data APIで取得できる公開動画のメタデータです。非公開動画や削除済み動画、権限のない情報は通常取得できません。実行時はYouTube API Servicesの利用規約やクォータ制限を確認し、必要以上に繰り返し取得しないようにします。
この記事でできること
- チャンネルIDからアップロード動画一覧を取得する
nextPageTokenを使って複数ページを取得する- 動画ID、タイトル、公開日、説明文などをCSVに保存する
- 必要に応じて再生数などの統計情報を追加する
search.listとの使い分けを理解する
全体の流れ
- APIキーを読み込む
channels.listでチャンネルのuploadsplaylist IDを取得するplaylistItems.listでアップロード動画一覧を取得する- ページングしながら全件を集める
- CSVに保存する
公式ドキュメントでも、チャンネルにアップロードされた動画を取得する例では、チャンネルの uploads playlistを取得してから playlistItems.list を呼び出す流れが紹介されています。
PlaylistItems: list - YouTube Data API
search.listを使わない理由
search.list でもチャンネルIDを指定して動画を検索できます。ただし、検索APIは検索結果として返るため、チャンネルの投稿一覧を安定して順番に集めたい用途では、uploads playlistを使うほうが素直です。
| 方法 | 向いている用途 | 補足 |
|---|---|---|
playlistItems.list | 特定チャンネルの投稿動画一覧 | uploads playlistをたどる。クォータコストは1 |
search.list | キーワードや条件で探す | 検索用途。クォータコストが高い |
Googleのクォータ表では、playlistItems.list は1ユニット、search.list は100ユニットです。単純に投稿動画一覧を作るだけなら、検索APIを使わないほうが効率的です。
Quota Calculator - YouTube Data API
事前準備
APIキーは .env に保存します。
YOUTUBE_API_KEY=ここにAPIキーを書く必要なライブラリをインストールします。
pip install requests python-dotenvAPIキーの管理方法は、次の記事で整理しています。
APIキーを外部ファイルで管理する方法|.envとconfig.iniの使い分け
チャンネルIDからuploads playlist IDを取得する
まず、channels.list を使って、チャンネルのアップロード動画が入っている再生リストIDを取得します。
import os
import requests
from dotenv import load_dotenv
load_dotenv()
API_KEY = os.getenv("YOUTUBE_API_KEY")
if not API_KEY:
raise RuntimeError("YOUTUBE_API_KEY が設定されていません")
def get_uploads_playlist_id(channel_id: str) -> str:
url = "https://www.googleapis.com/youtube/v3/channels"
params = {
"part": "contentDetails",
"id": channel_id,
"key": API_KEY,
}
response = requests.get(url, params=params, timeout=30)
response.raise_for_status()
data = response.json()
if not data["items"]:
raise RuntimeError("チャンネルが見つかりませんでした")
return data["items"][0]["contentDetails"]["relatedPlaylists"]["uploads"]uploads は、そのチャンネルに投稿された動画が入る再生リストです。以降は、この再生リストをページングしながら取得します。
動画一覧をページング取得する
playlistItems.list は、1回のリクエストで最大50件まで取得できます。さらに取得する場合は、レスポンスに含まれる nextPageToken を次のリクエストに渡します。
def get_playlist_items(playlist_id: str, max_pages: int | None = None) -> list[dict]:
url = "https://www.googleapis.com/youtube/v3/playlistItems"
items = []
page_token = None
page_count = 0
while True:
params = {
"part": "snippet,contentDetails",
"playlistId": playlist_id,
"maxResults": 50,
"key": API_KEY,
}
if page_token:
params["pageToken"] = page_token
response = requests.get(url, params=params, timeout=30)
response.raise_for_status()
data = response.json()
items.extend(data.get("items", []))
page_count += 1
if max_pages is not None and page_count >= max_pages:
break
page_token = data.get("nextPageToken")
if not page_token:
break
return itemsmax_pages を用意しておくと、動作確認時に最初の1ページだけ取得できます。いきなり全件取得するより、まず少量で確認するほうが安全です。
CSVに保存する
取得した動画一覧から、分析に使いやすい項目だけを取り出してCSVに保存します。
import csv
from pathlib import Path
def normalize_playlist_item(item: dict) -> dict:
snippet = item["snippet"]
content_details = item["contentDetails"]
return {
"video_id": content_details["videoId"],
"title": snippet.get("title", ""),
"published_at": content_details.get("videoPublishedAt", ""),
"channel_id": snippet.get("channelId", ""),
"channel_title": snippet.get("channelTitle", ""),
"position": snippet.get("position", ""),
"description": snippet.get("description", ""),
}
def save_csv(rows: list[dict], csv_path: Path) -> None:
csv_path.parent.mkdir(parents=True, exist_ok=True)
fieldnames = [
"video_id",
"title",
"published_at",
"channel_id",
"channel_title",
"position",
"description",
]
with csv_path.open("w", encoding="utf-8-sig", newline="") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(rows)説明文は長くなることがあります。CSVで扱いにくい場合は、最初は説明文を外して保存しても問題ありません。
実行コード全体
ここまでをまとめたコードです。まずは max_pages=1 で動作確認し、問題なければ None に変更します。
from pathlib import Path
CHANNEL_ID = "UCxxxxxxxxxxxxxxxxxxxxxx"
uploads_playlist_id = get_uploads_playlist_id(CHANNEL_ID)
print("uploads playlist:", uploads_playlist_id)
items = get_playlist_items(uploads_playlist_id, max_pages=1)
rows = [normalize_playlist_item(item) for item in items]
csv_path = Path("outputs/youtube/channel_videos.csv")
save_csv(rows, csv_path)
print(f"saved: {csv_path}")
print(f"rows: {len(rows)}")全件取得したい場合は次のようにします。
items = get_playlist_items(uploads_playlist_id, max_pages=None)再生数などの統計情報を追加する
playlistItems.list で取得できるのは、主に再生リスト内の動画情報です。再生数やコメント数を追加したい場合は、取得した動画IDを使って videos.list を呼び出します。
videos.list では、id にカンマ区切りで複数の動画IDを渡せます。1回で扱える件数に合わせて、50件ずつ分割すると扱いやすいです。
def chunked(values: list[str], size: int) -> list[list[str]]:
return [values[i:i + size] for i in range(0, len(values), size)]
def get_video_statistics(video_ids: list[str]) -> dict[str, dict]:
url = "https://www.googleapis.com/youtube/v3/videos"
stats_by_id = {}
for chunk in chunked(video_ids, 50):
params = {
"part": "statistics,contentDetails",
"id": ",".join(chunk),
"key": API_KEY,
}
response = requests.get(url, params=params, timeout=30)
response.raise_for_status()
data = response.json()
for item in data.get("items", []):
stats_by_id[item["id"]] = {
"view_count": item.get("statistics", {}).get("viewCount"),
"like_count": item.get("statistics", {}).get("likeCount"),
"comment_count": item.get("statistics", {}).get("commentCount"),
"duration": item.get("contentDetails", {}).get("duration"),
}
return stats_by_id統計情報は動画や設定によって欠けることがあります。欠損がある前提で保存するほうが後続分析で扱いやすいです。
取得後にできる分析
- 投稿日ごとの投稿本数を集計する
- タイトルに含まれる単語を集計する
- 再生数の多い動画と投稿時期を比較する
- 動画時間と再生数の関係を見る
- 特定シリーズや企画の投稿頻度を確認する
この段階では、まだ「動画一覧の取得」が目的です。分析記事に使う場合は、取得日、対象チャンネル、取得項目、欠損の有無をメモしておくと、後で読み返しやすくなります。
動画一覧を取得したあとに、通常動画・ライブ配信アーカイブ・Shortsなどの動画種別や、ゲーム・雑談・音楽などの独自カテゴリを付けたい場合は、YouTube APIで取得した動画一覧を分析用データセットに整える方法で整理しています。
よくあるつまずき
チャンネルIDがわからない
チャンネルURLがハンドル形式の場合、URLだけではチャンネルIDが見えにくいことがあります。公式APIで検索する方法もありますが、検索APIはクォータコストが高いため、最初はYouTube Studioやページ情報、既存ツールでチャンネルIDを確認するほうが簡単です。
取得件数が想定より少ない
max_pages を指定している場合は、そのページ数で止まります。全件取得したい場合は max_pages=None にします。また、非公開動画や削除済み動画は通常の公開データとして取得できません。
クォータが不安
まず1ページだけ取得し、必要な項目が取れているか確認します。統計情報を追加する videos.list もコストは1ですが、不要な項目を何度も取り直さないように、CSVやJSONで途中保存しておくとよいです。
関連記事
- YouTube Data API v3入門|APIキーで動画情報を取得するPython手順
- APIキーを外部ファイルで管理する方法|.envとconfig.iniの使い分け
- YouTube APIで取得した動画一覧を分析用データセットに整える方法|動画種別・カテゴリ付与まで
- YouTubeの情報を取得する方法まとめ|公式API・字幕・チャット・文字起こしの使い分け
まとめ
チャンネルの動画一覧を取得する場合は、channels.list で uploads playlist IDを取得し、playlistItems.list でページングしながら動画一覧を取得する流れが扱いやすいです。
検索APIは条件検索には便利ですが、投稿動画一覧を作るだけならクォータ面でも用途面でもuploads playlistを使うほうが明確です。CSVに保存しておけば、投稿頻度、タイトル傾向、再生数との関係など、後続の分析に進みやすくなります。