YouTube APIを使って視聴数ランキングを表示する(PHP)

特定チャンネルの動画を視聴数順で取得し、ランキング表示する実装方法を解説します。今回は「直近3ヶ月以内に投稿された動画」に絞ったランキング取得を例にします。

事前準備

  1. Google Cloud Console でプロジェクトを作成
  2. YouTube Data API v3 を有効化
  3. 認証情報から APIキー を発行
  4. 対象チャンネルの チャンネルID を確認(チャンネルページのURL末尾など)

⚠️ APIキーは必ず環境変数や設定ファイルで管理し、ソースコードに直書きしないようにしましょう。

基本実装

<?php// =============================// 設定// =============================$DEVELOPER_KEY = getenv('YOUTUBE_API_KEY'); // 環境変数から取得を推奨$CHANNEL_ID = 'UCxxxxxxxxxxxxxxxxxxxxxxx'; // 対象チャンネルID$MAX_RESULTS = 5; // 取得件数(最大50)$MONTHS_AGO = 3; // 何ヶ月前まで遡るか// 期間の起点日時をISO 8601形式で生成$PERIOD = date('Y-m-d', strtotime("-{$MONTHS_AGO} month")) . 'T00:00:00Z';// =============================// APIリクエスト// =============================$params = [ 'type' => 'video', 'part' => 'snippet', 'maxResults' => $MAX_RESULTS, 'regionCode' => 'JP', 'channelId' => $CHANNEL_ID, 'order' => 'viewCount', // 視聴数順(他: date / rating / relevance) 'publishedAfter'=> $PERIOD, 'key' => $DEVELOPER_KEY,];$url = 'https://www.googleapis.com/youtube/v3/search?' . http_build_query($params);$result = file_get_contents($url);if ($result === false) { die('APIリクエストに失敗しました。');}$result = json_decode($result, true);if (isset($result['error'])) { die('APIエラー: ' . $result['error']['message']);}// =============================// データ整形// =============================$rankingList = [];foreach ($result['items'] as $item) { $rankingList[] = [ 'videoId' => $item['id']['videoId'], 'title' => $item['snippet']['title'], 'description' => $item['snippet']['description'], 'thumbnail_medium' => $item['snippet']['thumbnails']['medium']['url'], 'publishedAt' => $item['snippet']['publishedAt'], 'channelTitle' => $item['snippet']['channelTitle'], ];}
PHP

http_build_query() を使うと、配列から安全にURLクエリ文字列を生成できます(特殊文字の自動エスケープつき)。

HTML出力

// =============================// 出力// =============================?><ol class="ranking-list"><?php foreach ($rankingList as $rank => $video): ?> <li class="ranking-item"> <span class="rank-number"><?= $rank + 1 ?></span> <a href="https://www.youtube.com/watch?v=<?= htmlspecialchars($video['videoId']) ?>" target="_blank"> <img src="<?= htmlspecialchars($video['thumbnail_medium']) ?>" alt="<?= htmlspecialchars($video['title']) ?>"> <div class="video-info"> <h3><?= htmlspecialchars($video['title']) ?></h3> <p class="published"><?= date('Y年m月d日', strtotime($video['publishedAt'])) ?></p> <p class="description"><?= htmlspecialchars(mb_substr($video['description'], 0, 80)) ?>...</p> </div> </a> </li><?php endforeach; ?></ol>
PHP

htmlspecialchars() で出力時のXSS対策を忘れずに。

視聴数も取得したい場合(videos.list の併用)

search.list のレスポンスには実際の視聴数が含まれません。視聴数を表示したい場合は、取得したビデオIDを使って videos.list を追加で呼び出す必要があります。

// videoIdをカンマ区切りで結合$videoIds = implode(',', array_column($rankingList, 'videoId'));$statsParams = [ 'part' => 'statistics', 'id' => $videoIds, 'key' => $DEVELOPER_KEY,];$statsUrl = 'https://www.googleapis.com/youtube/v3/videos?' . http_build_query($statsParams);$statsResult = json_decode(file_get_contents($statsUrl), true);// rankingListに視聴数をマージ$statsMap = [];foreach ($statsResult['items'] as $item) { $statsMap[$item['id']] = $item['statistics']['viewCount'];}foreach ($rankingList as &$video) { $video['viewCount'] = $statsMap[$video['videoId']] ?? 0;}unset($video);
PHP

これで $video['viewCount'] に視聴数が入ります。

応用:キャッシュで API クォータを節約する

YouTube Data API v3 には**1日あたりのクォータ制限(デフォルト10,000ユニット)**があります。毎回APIを叩くのではなく、結果をファイルやDBにキャッシュしておくのがベストプラクティスです。

$cacheFile = __DIR__ . '/cache/youtube_ranking.json';$cacheExpiry = 3600; // 1時間キャッシュif (file_exists($cacheFile) && (time() - filemtime($cacheFile) < $cacheExpiry)) { // キャッシュから読み込み $rankingList = json_decode(file_get_contents($cacheFile), true);} else { // APIから取得(上記コード) // ... // キャッシュに保存 file_put_contents($cacheFile, json_encode($rankingList));}
PHP

よくあるエラーと対処法

エラー内容原因対処
keyInvalidAPIキーが誤っているCloud ConsoleでAPIキーを確認
quotaExceeded1日のクォータ超過キャッシュ導入、または翌日まで待つ
forbiddenAPIが有効化されていないYouTube Data API v3 を有効化
結果が0件チャンネルIDの誤り・対象期間に動画なしチャンネルIDを再確認

まとめ

  • order=viewCount + publishedAfter で期間絞り込みランキングが取得できる
  • 実際の視聴数表示は videos.list との2段階取得が必要
  • APIキーは環境変数管理 & 結果はキャッシュでクォータを節約
  • 出力時は必ず htmlspecialchars() でXSS対策を行う

read next