0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Google スプレッドシートに記載した goo.gl を元の URL へ戻す

Last updated at Posted at 2025-08-08

概要

Google は goo.gl 短縮 URL サービスを終了することを発表しました。その後一部変更され、使用頻度の低い URL は削除、使用頻度の高い URL は継続されることになりました。

私が昔使っていた Google SpreadSheet の中には goo.gl 短縮 URL が沢山あります。サービス縮小までに元の URL に置換する必要がでてきました。

何をする?

  1. http://goo.gl または https://goo.gl から始まる文字列を含むセルを探す
  2. リダイレクト先 URL を取得する
    1. ただし「もうじきこのURLは使えなくなるよ」の画面へリダイレクトされる場合がある
    2. この場合はリダイレクト先URLも https://goo.gl になる
  3. リダイレクト先も https://goo.gl だった場合はソースコードの中から redirect-url="https://*" を探して URL を取得する

image.png

免責事項

ここから下に実際のソースコードがあります。

  • 何が起こっても知りません。自己責任で使用してください。
  • 実行する前にスプレッドシートをコピー(複製)することを強くお勧めします。
  • 転送先URLの事情によりもう一度リダイレクトされる場合はうまく取得できません。

ソースコード

ChatGPT と試行錯誤してまともに動くようになったコードがこれです。

Google Apps Script
function expandAllGooGlUrlsInSpreadsheet() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheets = ss.getSheets();
  const maxRedirect = 3;

  sheets.forEach(sheet => {
    const range = sheet.getDataRange();
    const values = range.getValues();

    let updated = false;

    for (let i = 0; i < values.length; i++) {
      for (let j = 0; j < values[i].length; j++) {
        const cell = values[i][j];
        if (typeof cell === 'string' && /https?:\/\/goo\.gl/.test(cell)) {
          // セル内のgoo.gl URLを全部探す
          const urls = extractGooGlUrls(cell);
          let newCell = cell;

          urls.forEach(shortUrl => {
            try {
              const expandedUrl = expandUrlWithRedirectHandling(shortUrl, maxRedirect);
              if (expandedUrl && expandedUrl !== shortUrl) {
                newCell = newCell.replace(shortUrl, expandedUrl);
              }
            } catch (e) {
              Logger.log('Error expanding URL: ' + shortUrl + ' - ' + e.message);
            }
          });

          if (newCell !== cell) {
            values[i][j] = newCell;
            updated = true;
          }
        }
      }
    }

    if (updated) {
      range.setValues(values);
    }
  });
}

/**
 * セルの文字列から http://goo.gl で始まるURLを全部抽出
 * @param {string} text 
 * @returns {string[]}
 */
function extractGooGlUrls(text) {
  const regex = /https?:\/\/goo\.gl\/[A-Za-z0-9]+/g;
  const matches = text.match(regex);
  return matches ? matches : [];
}

/**
 * 短縮URLを展開し、条件に応じて data-redirect-url を探す
 * @param {string} url 
 * @param {number} maxRedirect 
 * @returns {string} 最終的な展開先URL
 */
function expandUrlWithRedirectHandling(url, maxRedirect) {
  let currentUrl = url;

  for (let i = 0; i < maxRedirect; i++) {
    const response = UrlFetchApp.fetch(currentUrl, { muteHttpExceptions: true, followRedirects: false });
    const code = response.getResponseCode();

    if (code >= 300 && code < 400) {
      // リダイレクト先URLを取得
      let location = response.getHeaders()['Location'] || response.getHeaders()['location'];

      if (!location) {
        throw new Error('Redirect location header not found for URL: ' + currentUrl);
      }

      // URLが相対パスの場合は絶対パスに変換
      location = toAbsoluteUrl(currentUrl, location);

      if (location.includes('goo.gl')) {
        // goo.gl ドメインならHTMLの data-redirect-url を抽出する
        const htmlResponse = UrlFetchApp.fetch(location, { muteHttpExceptions: true });
        const html = htmlResponse.getContentText();
        const redirectUrl = extractDataRedirectUrl(html);
        if (redirectUrl) {
          currentUrl = redirectUrl;
          // これで終わらずに次のループで展開を続ける
        } else {
          currentUrl = location;
        }
      } else {
        currentUrl = location;
      }
    } else {
      // リダイレクトではない場合は終わり
      break;
    }
  }
  return currentUrl;
}

/**
 * 相対パスのLocationを絶対URLに変換
 * @param {string} baseUrl 
 * @param {string} location 
 * @returns {string}
 */
function toAbsoluteUrl(baseUrl, location) {
  if (/^https?:\/\//.test(location)) {
    return location;
  }
  // baseUrlのドメイン部分を抽出
  const urlObj = new URL(baseUrl);
  if (location.startsWith('/')) {
    return urlObj.protocol + '//' + urlObj.host + location;
  } else {
    // 相対パスのケース
    const path = urlObj.pathname.split('/');
    path.pop(); // 最後のファイル名を除く
    const newPath = path.join('/') + '/' + location;
    return urlObj.protocol + '//' + urlObj.host + newPath;
  }
}

/**
 * HTMLソースから data-redirect-url="..." を抽出
 * @param {string} html 
 * @returns {string|null}
 */
function extractDataRedirectUrl(html) {
  const regex = /data-redirect-url="([^"]+)"/;
  const match = html.match(regex);
  return match ? match[1] : null;
}

使い方

  1. Google スプレッドシートを開く
  2. 拡張機能 → Apps Script を開く
  3. 上記コードを貼り付ける
  4. 保存する( Ctrl + S またはフロッピーディスクのボタンをクリック)
  5. expandAllGooGlUrlsInSpreadsheet を実行
  6. 初回は「権限承認」が求められるので許可する
  7. シート内の goo.gl URL が元URLに置き換わる

関連リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?