PageSpeed Insights API を使って Python にページの平均点を計測させる
はじめに
今所属しているプロダクトでは、検索結果の上位表示やサイト閲覧時のストレス軽減を目的に PageSpeed Insights (以下、PSI )を指標にページスピードの改善を測っています。
改善結果を Before/After で計測していくわけですが、PSI の点数は計測するタイミングによっては余裕で10〜30点のブレが出たりします。
そういうわけで、僕のチームでは1ページ1計測ではなく、数回計測して
- 平均点
- 測定回数(15回以上)
- ブレが大きい場合は最低点・最高点
を記載する方式でやっていくことにしました。
が、これだと計測したいページが増えるほどに、 分析
ボタンをカチっとやって待つ時間が当然とてもつらいものになります。
今回は API を使ってこれを効率化してみました。
対象読者像
- API を使ってデータを取得したいプログラミング初学者〜エンジニア1年目
完成品
kotahashihama/psi-score-collector
API キーの取得
PageSpeed Insights API からデータを取得するには、アクセス時にパラメーターとして添える形で API キーが必要になります。
以下のページで取得できます。
PageSpeed Insights API を使ってみる | Google Developers
プロジェクトコード内に API キーをそのままで置いておくのはセキュリティ上よくないので、ライブラリの python-dotenv
を使い .env
で環境変数として管理するようにしました。
pip install python-dotenv
from dotenv import load_dotenv
load_dotenv()
import os
API_KEY = os.getenv('API_KEY')
API_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
設定項目を用意
設定した測定回数ごとに順々に測定させていきたいので、必要なのは以下の項目です。
# 測定回数
measurement_count = 3;
# 測定対象 URL
url_list = [
'https://www.google.com/',
'https://www.yahoo.co.jp/',
'https://www.bing.com/'
]
設定内容は処理から切り離した形にするのが本来よさそうなんですが、今回はこれでいきます。
メイン処理の記述
URL ごとに
- ステップ数
- モバイルの点数
- パソコンの点数
を出力させていき、最後に測定完了のメッセージを表示させます。
print('\n'.join(map(str, url_list)))
print(f'を測定中...({measurement_count}回計測)')
for i, url in enumerate(url_list):
print(f'\n({i + 1}/{len(url_list)}) {url}')
measure('mobile')
measure('desktop')
print('\n' + '=' * 60)
print('\n測定完了!')
点数を取得させよう
SPI の API にアクセスする URL とパラメーターを用意しておきます。
api_url = 'https://www.googleapis.com/pagespeedonline/v5/runPagespeed'
api_key = config.API_KEY
payload = { 'key': api_key }
上のほうで作った config.py
では、.env
から読み込んだ環境変数を持たせています。
import config
で config
を読み込み、api_key
へ値をセットしておきましょう。
点数を取ってくる処理
まず、以下がコードの全貌です。
def measure(device):
device_name = {
'mobile': 'モバイル',
'desktop': 'パソコン'
}
print(f'[ {device_name[device]} ]')
payload['strategy'] = device
url_name = api_url + "?url=" + url
scores = []
for i in range(measurement_count):
result = requests.get(url_name, params = payload)
result_json = result.json()
result_score = result_json['lighthouseResult']['categories']['performance']['score']
displayed_score = math.floor(result_score * 100)
scores.append(displayed_score)
print(displayed_score, end=' ')
score_average_raw = numpy.average(scores)
score_average = Decimal(str(score_average_raw)).quantize(Decimal('0.1'), rounding=ROUND_HALF_UP)
score_max = numpy.amax(scores)
score_min = numpy.amin(scores)
print(f'\n平均 {score_average} 点(最低 {score_min} 点、最高 {score_max} 点)')
この処理の中では大きく2種類のライブラリが使われていて
- API にアクセス
- 結果を計算
しています。
(今回は触れませんが、Python ライブラリは Poetry 等で依存関係管理をすると、チームメンバーにも共有しやすいかと思います)
API にアクセスするライブラリ
requests
という Python ライブラリを使います。
pip install requests
import requests
result = requests.get(url_name, params = payload)
result_json = result.json()
result_score = result_json['lighthouseResult']['categories']['performance']['score']
get()
で API にアクセスし、json()
で結果を JSON 化し、点数が格納されている score
までをたどっています。
結果を計算するライブラリ
math
numpy
decimal
という計算系の Python ライブラリを使います。
このうち、numpy
は標準で入っていないため、pip でインストールします。
pip install numpy
import numpy
decimal
では Decimal
オブジェクトと四捨五入のための定数 ROUND_HALF_UP
だけを使うため、インポート時にこの形で読み込みます。
from decimal import Decimal, ROUND_HALF_UP
score_average_raw = numpy.average(scores)
score_average = Decimal(str(score_average_raw)).quantize(Decimal('0.1'), rounding=ROUND_HALF_UP)
score_max = numpy.amax(scores)
score_min = numpy.amin(scores)
-
numpy
では点数からそれぞれ平均点の計算、最高点、最低点のみを取得 -
decimal
のDecimal
オブジェクトでは平均値を四捨五入して小数点第一位までを表示
しています。
使ってみる
実行したら、あとは放置で点数を収集してくれます。
終了を知らせるのに terminal-notifier とかを使うとより便利かもしれません。
py main.py
こんな感じで計測結果が溜まっていきます。
まとめ
データを取得〜加工は、めちゃめちゃファンダメンタルな部分なので業務のいろんなところで活かせそうですね。
エンジニアたるもの、息を吸って吐くようにこういったツールを作れるようになりたい所存です。
Discussion