Python で HAR ファイルから散布図を作成

Web サイトの構成を可視化するため、Python で HAR (HTTP ARchive) ファイルをパースし散布図を試しに作ってみました。

今回作成した散布図の内容は以下の通りです。

  • 横軸は time (処理時間 (ミリ秒))
  • 縦軸は bodySize (レスポンスボディのサイズ)
  • MIME タイプのサブタイプ別に色分け

今回は Anaconda に予め含まれているライブラリを使用する事にします。

今回のソースは http://github.com/fits/try_samples/tree/master/blog/20170514/

はじめに

HAR ファイルは ChromeFirefox の開発ツールで取得できますが、簡易なものは PhantomJS の examples/netsniff.js で取得できるので今回はこれを使いました。

HAR の取得
phantomjs netsniff.js <URL>

netsniff.js では console.log で HAR の内容を出力するようになっています。

HAR ファイルの取得例
phantomjs netsniff.js https://www.・・・ > a.har

HAR ファイルは以下のような JSON 形式のファイルとなっています。

HAR ファイル例
{
  "log": {
    ・・・
    "entries": [
      {
        ・・・
        "time": 4474,
        "request": {
          ・・・
        },
        "response": {
          ・・・
          "bodySize": 473,
          "content": {
            "size": 473,
            "mimeType": "text/html;charset=UTF-8"
          }
        },
        "cache": {},
        "timings": {
          ・・・
          "wait": 3813,
          "receive": 661,
          "ssl": -1
        },
        ・・・
      },
      ・・・
    ]
  }
}

netsniff.js では、timings 内の wait と receive 以外の値は固定値(0 か -1)が設定されるようになっています。

1. seaborn の pairplot 使用

まずは、seaborn の pairplot を使って散布図を描画してみます。 (pairplot はデフォルトが散布図になっているようです)

pairplot は基本的にデータ内の数値変数の全ての組み合わせをグラフ化するものですが、x_varsy_vars を指定する事で特定の組み合わせに限定したグラフだけを描画する事も可能です。

色分けする項目は hue で指定できるようになっています。

複数のグラフをグリッド表示する事を想定しているため、個々のグラフのデフォルトサイズが小さく設定されていますが、size で変更する事が可能です。

har_scatter_plot1.py
import sys
import json
import codecs
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

# HAR ファイルの読み込みと Python オブジェクト化
data = json.load(codecs.open(sys.argv[1], 'r', 'utf-8'))

to_subtype = lambda mtype: mtype.split(';')[0].split('/')[-1]
# 特定の項目を抜き出す処理
convert = lambda d: {
    'subType': to_subtype(d['response']['content']['mimeType']),
    'bodySize': d['response']['bodySize'],
    'time': d['time']
}
# DataFrame 化
df = pd.DataFrame(list(map(convert, data['log']['entries'])))

# 散布図の描画
sns.pairplot(df, hue = 'subType', x_vars = 'time', y_vars = 'bodySize', size = 10)

imgfile = "%s_1.png" % sys.argv[1]

# グラフの保存
plt.savefig(imgfile)
実行例
python har_scatter_plot1.py a.har

実行結果例

a.har_1.png

f:id:fits:20170514210328p:plain

b.har_1.png

f:id:fits:20170514210341p:plain

2. サブタイプ毎に plot

pairplot の結果ではサブタイプ毎の色が固定されておらず、複数の Web ページを比較する用途には適していません。

そこで、サブタイプ毎の散布図を重ねて描画してみました。

har_scatter_plot2.py
import sys
import json
import codecs
import pandas as pd
import matplotlib.pyplot as plt

・・・
# サブタイプと色のマッピング
color_map = {
    'javascript': 'blue',
    'x-javascript': 'blue',
    'json': 'green',
    'gif': 'tomato',
    'jpeg': 'red',
    'png': 'pink',
    'html': 'lime',
    'css': 'turquoise'
}

df = pd.DataFrame(list(map(convert, data['log']['entries'])))

ax = plt.figure().add_subplot(1, 1, 1)

for (k, c) in color_map.items():
    # 指定サブタイプのデータを抽出
    sdf = df[df['subType'] == k]

    if not sdf.empty:
        # c の色で散布図(scatter)を描画
        sdf.plot('time', 'bodySize', 'scatter', ax, c = c, label = k)

imgfile = "%s_2.png" % sys.argv[1]

plt.savefig(imgfile)
実行例
python har_scatter_plot2.py a.har

実行結果例

a.har_2.png

f:id:fits:20170514210415p:plain

b.har_2.png

f:id:fits:20170514210424p:plain