📹

YouTubeの公開されているプレイリストの動画情報をスプレッドシートに出力するGAS

に公開

だいたいGemini 2.5 Proに作ってもらいました
プロンプト

YouTubeの公開済プレイリストに含まれるすべての動画情報を一覧にしてGoogleSpreadSheetに書き出すGASを作ってください。



要件

- GASは手動でプレイリストのURLを渡して実行します

- 一覧には動画のタイトルとアーティスト名を出力してください。タイトルは動画へのリンクにしてください

- 一覧の並び順はプレイリストの並び順にしてください

- 一覧には重複は作らないようにしてください
/**
 * 指定されたYouTubeプレイリストの動画情報をスプレッドシートに書き出すメイン関数
 */
function exportPlaylistVideosToSheet() {
  // ▼▼▼ ここに情報を取得したいYouTubeプレイリストのURLを貼り付けてください ▼▼▼
  const PLAYLIST_URL = 'https://www.youtube.com/playlist?list=';
  // ▲▲▲ ここまで ▲▲▲

  // URLからプレイリストIDを抽出
  const playlistId = extractPlaylistIdFromUrl(PLAYLIST_URL);
  if (!playlistId) {
    SpreadsheetApp.getUi().alert('有効なYouTubeプレイリストのURLではありません。\nURLの形式を確認してください。');
    return;
  }

  try {
    // プレイリストから動画情報を取得(重複排除済み)
    const videos = getVideosFromPlaylist(playlistId);

    // スプレッドシートに書き出し
    writeVideosToSheet(videos);

    SpreadsheetApp.getUi().alert('プレイリスト情報の書き出しが完了しました。');

  } catch (e) {
    Logger.log('エラーが発生しました: ' + e.toString());
    SpreadsheetApp.getUi().alert('エラーが発生しました。\n詳細: ' + e.message);
  }
}

/**
 * YouTubeのURLからプレイリストIDを抽出する関数
 * @param {string} url - YouTubeプレイリストのURL
 * @return {string|null} - プレイリストID、見つからない場合はnull
 */
function extractPlaylistIdFromUrl(url) {
  const regex = /[?&]list=([^&]+)/;
  const match = url.match(regex);
  return match ? match[1] : null;
}

/**
 * プレイリストIDを使用して、プレイリスト内の全動画情報を取得する関数
 * @param {string} playlistId - YouTubeプレイリストのID
 * @return {Array<Object>} - 動画情報の配列
 */
function getVideosFromPlaylist(playlistId) {
  let nextPageToken = null;
  const videoList = [];
  const processedVideoIds = new Set(); // 重複チェック用

  do {
    const response = YouTube.PlaylistItems.list('snippet', {
      playlistId: playlistId,
      maxResults: 50, // 一度に取得する最大件数
      pageToken: nextPageToken
    });

    for (const item of response.items) {
      const videoId = item.snippet.resourceId.videoId;

      // 重複がない場合のみリストに追加
      if (!processedVideoIds.has(videoId) && !isPrivateVideo(item)) {
        videoList.push({
          title: item.snippet.title,
          artist: item.snippet.videoOwnerChannelTitle,
          thumbnail: fetchThumbnailsUrl(item),
          videoId: videoId
        });
        processedVideoIds.add(videoId);
      }
    }
    nextPageToken = response.nextPageToken;
  } while (nextPageToken);

  return videoList;
}

/**
 * 非公開状態の動画かを判定する
 */
function isPrivateVideo(item) {
  return item.snippet.title == 'Private video';
}

/**
 * 動画に設定されたサムネイルを大きい順から見て存在するものを返す
 * @params Video video 動画情報をオブジェクト
 */
function fetchThumbnailsUrl(video) {
  return video.snippet.thumbnails?.maxres?.url 
  ?? video.snippet.thumbnails?.standard?.url 
  ?? video.snippet.thumbnails?.high?.url 
  ?? video.snippet.thumbnails?.medium?.url
  ?? video.snippet.thumbnails?.default?.url
  ?? ''
}

/**
 * 取得した動画情報をスプレッドシートに書き出す関数
 * @param {Array<Object>} videos - 動画情報の配列
 */
function writeVideosToSheet(videos) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  sheet.clear(); // シートの内容を一旦クリア

  // ヘッダー行を設定
  const headers = ['サムネイル', 'タイトル', 'アーティスト名'];
  sheet.getRange(1, 1, 1, headers.length)
    .setValues([headers])
    .setFontWeight('bold');

  if (videos.length === 0) {
    return;
  }

  // サムネイルを書き込む情報
  const thumbnailValues = videos.map(video => {
    const thumbnailText = '=IMAGE("' + video.thumbnail + '")';
    return [thumbnailText];
  });
  
  // スプレッドシートに書き込むためのデータを作成
  const richTextValues = videos.map(video => {
    // タイトルに動画へのリンクを設定したリッチテキストを作成
    const videoUrl = `https://www.youtube.com/watch?v=${video.videoId}`;
    const richTextTitle = SpreadsheetApp.newRichTextValue()
      .setText(video.title)
      .setLinkUrl(videoUrl)
      .build();

    const ricthTextArtist = SpreadsheetApp.newRichTextValue()
       .setText(String(video.artist)) // Stringに変換しないとエラーになった
       .build();

    // setRichTextValuesはricthTextValueしか書き込めない
    return [richTextTitle, ricthTextArtist];
  });
  
  // データをシートに一括で書き込み
  sheet.getRange(2, 1, thumbnailValues.length, 1)
    .setValues(thumbnailValues);

  sheet.getRange(2, 2, richTextValues.length, richTextValues[0].length)
   .setRichTextValues(richTextValues);
    
  // 行列幅を自動調整
  // サムネイルをいいサイズで表示したいので一部を手動設定しています
  sheet.setColumnWidth(1, 150) 
  sheet.autoResizeColumns(2, 3);
  sheet.setRowHeights(2, richTextValues.length, 100);
}


Discussion