GoogleのPageSpeedAPIで複数サイトの表示速度をGoogleスプレッドシートに毎週自動で書き出す

Google PageSpeed Insightsで複数サイトを一度に計測したい

Google PageSpeed Insightsというサービスではサイトの速度を計測することができるのですが、一度にひとつのサイトしか計測できないので複数サイトを一度に計測したい場合にかなり時間がかかるということがありました。
そこでこのサービスの APIを利用して複数サイトを一気に計測してみたいと思います。
いろんな方法があるのですが、今回はGoogleAppScriptを使ってGoogleスプレッドシートに書き出してみたいと思います。
やってることとしてはスプレッドシートの操作なのでExcelVBAに近いのですが、GoogleAppScriptはJavascriptの記法で書けるのでExcelVBAで書くよりも汎用的で勉強になります。

最終的に今回のスクリプトでは下記の機能を実装しました。

  • 複数URLをGooglePageSpeedAPIにかけた結果をGoogleスプレッドシートに書き出す
  • 上記作業が毎週決まった曜日と時間帯で自動で実行されるようにする
  • 作業が完了したらChatworkで連絡されるようにする

今回できたスクリプト。
https://github.com/katsunory/auto_multi_pagespeed_insights

Googleスプレッドシートと連携したGoogleAppScriptを書く

まず、おもむろにGoogleスプレッドシートを作成します。
A列に複数のURL、B〜列にスコアが記入される想定です。
また、PageSpeedInsightではPC、SPそれぞれのページ速度のスコアを取得することが可能ですが、今回はシートごとに「?_PC」「?_SP」のようなシート名からどちらのスコアを取得するかを決めたいと思います。
次に、上メニューのツール > スクリプトエディタからスクリプトエディタを立ち上げます。
プロジェクト名とスクリプトファイル名を適当に決め次の関数を記述します。

/**
 * ページの表示速度を測定する
 */
function insightPagespeed() {

  // スプレッドシート全体に関わる変数
  var API_TOKEN_PAGESPEED = getScriptProperty('API_TOKEN_PAGESPEED');
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheets = ss.getSheets(); // スプレッドシート内の全シートを取得

  // 各シートごとに関わる変数
  var sheetIndex = getScriptProperty('sheetIndex') ? parseInt(getScriptProperty('sheetIndex')) : 0; // 何番目のシートを処理するか
  var sheet = sheets[sheetIndex];
  var lastRow = sheet.getLastRow(); // そのシートの最終行を取得
  var today = Moment.moment().format('M月D日');

  // PageSpeedInsightsAPIのリクエストに関わる変数
  var device = sheet.getName().substr(-2); // シート名の後ろ2文字を切り出してデバイスを取得
  var strategy = device === 'PC' ? 'desktop' : 'mobile'; // デバイス別にクエリの値を取得

  // 同一シート内の各処理ごとに関わる変数
  var row = getScriptProperty('row') ? parseInt(getScriptProperty('row')) : 2; // 何番目の行から処理するか
  var urls = sheet.getRange(row, 1, lastRow - row + 1, 1).getValues(); // URL配列を現在の行から最後まで取得
  var scores = [];

  // 再起動用に開始時間を取得
  var start = Moment.moment()

  // 各行のURLのページスピード書き込みの処理が途中であれば最終列を、なければその次の列を取得する
  var column;
  if (row > 2) {
    column = sheet.getLastColumn();
  } else {
    column = sheet.getLastColumn() + 1;
    sheet.getRange(1,column).setValue(today); // 今日の日付を1行目に書き込む
  }

  Logger.log(sheetIndex + 'シート目' + column + '列' + row + '行目からのURLを処理中...');

  // 取得した全URLに対して処理
  for (var i = 0; i < urls.length; i++) {

    // URLが空の場合はスキップ
    var url = urls[i][0];
    if (!url) continue;

    // リクエストURLを作成
    var request = 'https://www.googleapis.com/pagespeedonline/v2/runPagespeed?url=' + url + '&key=' + API_TOKEN_PAGESPEED + '&strategy=' + strategy;

    // URLをAPIに投げてみてエラーが返ってくる場合はログに残す
    try {
      var response = UrlFetchApp.fetch(request, {muteHttpExceptions: true });
    } catch (err) {
      Logger.log(err);
      return(err);
    }

    // 返ってきたjsonをパース
    var parsedResult = JSON.parse(response.getContentText());
    var score = parsedResult.ruleGroups ? parsedResult.ruleGroups.SPEED.score : '-';

    // ページスピードスコアをscores配列に追加
    scores.push([score]);

    // 現在時間を取得して、開始から5分経過していたらforループ処理を中断して再起動
    var now = Moment.moment()
    if (now.diff(start, 'minutes') >= 5) {
      Logger.log('5分経過しました。タイムアウト回避のため処理を中断して再起動します。')
      break;
    }
  }

  // 取得したスコアを一度に書き込む
  sheet.getRange(row, column, scores.length, 1).setValues(scores);
  Logger.log(sheetIndex + 'シート目' + column + '列' + row + '行目から' + (row + scores.length) + '行目まで入力を行いました。')

  // rowを次の再起動用に設定
  row = row + scores.length;
  setScriptProperty('row', row);

  // 最終行まで処理していない場合は次の関数を再起動。最終行まで処理している場合は保存していた行を削除
  if (row < lastRow) {
    setTrigger('insightPagespeed');

  } else {
   deleteScriptProperty('row');

    sheetIndex++;

    // sheetIndexをスクリプトプロパティにセット。最終シートまで処理した場合はスクリプトプロパティを全て削除してChatworkで結果を共有
    if (sheetIndex < sheets.length) {
      setScriptProperty('sheetIndex', sheetIndex);
      setTrigger('insightPagespeed');
    } else {
      deleteScriptProperty('sheetIndex');
      deleteTrigger();
      sendMessage();
    }
  }
}

ページ速度を取得するメインの関数です。
API_TOKEN_PAGESPEEDには自分のAPI_KEYを登録します。
API_KEYの取得は、まずGoogleDeveloversConsole - API Managerを開き、PageSpeed Insights APIを選択します。
画面上でAPIの有効、無効を選択できるので「有効」にします。
次にAPIを使用するために「認証情報を作成」という項目が出てくるので作成します。
英大文字小文字記号の何桁かの文字列が出てくるのでそれがAPI_KEYになります。

以下注意点的なものを書きます。

ver2のAPIを使用しよう

PageSpeedのAPIにはver1と2があり、今はどちらも使えるのですがなるべくver2を使った方が良さそうです。
APIに投げるURLのv2という部分でver2を指定します。v1ならver1になります。
詳しく調べたわけではないのですが、例えばver2だとmobileで速度のスコアだけでなくユーザビリティのスコアを出すことができるなど、返ってくるJSONも多少異なっています。
上記コードはver2用のものなのでver1では動かない可能性があります。

scriptPropertyについて

APIなど表に出したくないものや、1回の処理で終わりでなく複数の処理で使いまわしたい変数をスプレッドシートの裏に持っておくことができるのがscriptPropertyです。
PropertiesService.getScriptProperties().getProperty(key)などとして書くことができます。
今回は長いので別にfunctionを作りました。
便利なのでどんどん使っていきましょう。

Momentなどの便利ライブラリをリソース > ライブラリから登録

ライブラリのプロジェクトキーを入れる必要があります。
ググれば出てきます。

GoogleAppsScriptの連続実行時間

連続して実行できる時間に制限があり、おおよそ5分程度です。
なので、複数URLの数が少ないときはいいですが、多すぎて5分以内に実行できない場合は一度処理を止め、再度途中から実行する必要があります。

トリガー機能で自動実行する

毎週決まった曜日と時間帯に実行するのは、コードではなくプロジェクトのトリガー機能で行います。
メニューの時計マークをクリックし、メインの関数を時間手動型で好きなタイミングで設定します。

GoogleAppScriptを実行してみる

API_KEYを先程のコードに入れて、スプレッドシートのA2〜11になんらかのURLを入れてみます。
また、わかりやすいようにA1に「URL」と入れておきます。
次にスクリプトエディタの実行ボタンをクリックして実行します。
初回はスクリプトを実行するのに許可を求められることがあるので普通に許可します。

成功するとPageSpeedの速度を求めることができます。
また、残したログはスクリプトエディタの表示 > ログから見ることができます。

スプレッドシート内にボタンを置くこともできる

今回は自動実行なので必要ないですが、スプレッドシート内にボタンを置いてそこから実行することもできます。
挿入 > 図形描画から図形を書くことができるので、図形から四角形でも描画し、図形に「実行」などとテキストを書き保存します。
図形がスプレッドシートに配置されるので、図形上で右クリックなどをすると右上に出る逆三角形のメニューを開き、「スクリプトを割り当て」を選びます。
ここはfunction名を登録しボタンをクリックします。

スコアによって色分けする

こちらはスプレッドシート側の機能ですが、Excelのようにセル全体を選択して、表示形式 > 条件付き書式 > カラースケールで最小値と最大値などを設定すれば、ページスピードのスコアによって色分けがなされ、見やすくなります。