8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

はじめに

少し前の話ですが、「Apacheのアクセスログを何かに活用できないかしら」との話を社内で貰たので、勉強がてらデータ分析してみた内容を備忘録的に書きます。

データ分析・Apache・記事投稿、どれをとっても初心者のため拙い文章ですが、ご容赦くださいませ。

アクセスログの分析

モジュールのインポート

今回は下記のモジュールを使ってます。

# データの処理
import pandas as pd
import numpy as np

# グラフ表示
import plotly.express as px
from plotly import tools
import seaborn as sns
import matplotlib.pyplot as plt

# その他
import datetime,time
import ipaddress

データの読み込み

ログファイルをとりあえず全部読み込みました。

col_names = ['ip','c1','c2', 'datetime', 'timezone', 'request', 'status', 'size', 'referer', 'user_agent']
df = pd.read_csv("データのパス", sep=' ', dtype=str, names=col_names)
df[:1]

image.png

データの整形

IP version

IPv4とIPv6を分別したいのでipaddressモジュールを使って新しいカラムにIP Versionのデータを追加します。

def ipcheck(x):
    return ipaddress.ip_address(x.iloc[0]).version

df["ip_ver"] = np.nan
df["ip_ver"] = df.apply(ipcheck, axis=1)

端末情報

強引ですが、UserAgentからOSを判別してデータを追加します。

def device(x):
    ua = x.iloc[9]
    dev = "etc"
    if "iPhone" in ua:
        dev="iPhone"
    elif "Android" in ua:
        dev="Android"
    elif "Win" in ua:
        dev="Windows"
    elif "Mac" in ua:
        dev="Macintosh"
    elif "Linux" in ua:
        dev="Linux"
    return dev

df["device"] = np.nan
df["device"] = df.apply(device, axis=1)

日時

読み込んだ時に日時とタイムゾーンが分かれてしまったので、いい感じにPythonのdatetime型にして格納します。

#datetime,timezoneをpythonのdatetime型に変換して挿入
datetime_str = df.datetime + df.timezone
time_trimmed = datetime_str.map(lambda s: s.strip('[]').split('+')[0])
df['datetime'] = pd.to_datetime(time_trimmed, format='%d/%b/%Y:%H:%M:%S')

ヒートマップ用に時間だけのデータも追加します。(わざわざ追加しなくてもよかったかもですが…)

def hourcheck(x):
    dt = x.iloc[3]
    return dt.strftime('%H')

df["hour"] = np.nan
df["hour"] = df.apply(hourcheck, axis=1)

不要なデータの削除

カラム名をc1,c2と置いているところは「クライアントの識別子」と「認証ユーザー名」のようですが、今回のログでは特に情報無いため消します。タイムゾーンももう必要ないので消します。

del df['c1']
del df['c2']
del df['timezone']

円グラフで可視化してみる

まずplotly.expressを使って可視化してみます。

IPv4/IPv6の比率

数の多いstatus:200に絞ってIPv4/IPv6の比率を可視化してみます。

df_ip = df.pivot_table(index="ip_ver",columns="status",aggfunc='size',fill_value=0)

ip_fig_title = 'IPv4/v6比率'
ip_fig = px.pie(data_frame=df_ip,
       values='200',
       names=df_ip.index,
       hover_name=df_ip.index,
       labels={'ip_ver':'IP version','200':'count'})
ip_fig.update_layout(xaxis={'categoryorder':'category ascending'},  title=ip_fig_title)
ip_fig.update_traces(textinfo='percent+label')
ip_fig.show()

newplot.png
若干ですが、v4の方が多いみたい。

端末種別の割合

こちらもstatus:200に絞って端末種別の割合を表示してみます。

df_device = df.pivot_table(index="device",columns="status",aggfunc='size',fill_value=0)

ip_fig_title = 'IPv4/v6比率'
ip_fig = px.pie(data_frame=df_ip,
       values='200',
       names=df_ip.index,
       hover_name=df_ip.index,
       labels={'ip_ver':'IP version','200':'count'})
ip_fig.update_layout(xaxis={'categoryorder':'category ascending'},  title=ip_fig_title)
ip_fig.update_traces(textinfo='percent+label')
ip_fig.show()

newplot.png
Windows、iPhone、Androidで9割越えの結果に。
やはりAndroidよりiPhoneユーザの方が多いですね。

IPv4/IPv6それぞれの端末種別の割合

今度はIPv4/IPv6それぞれで端末種別の割合を見てみます。

df_device_ip = df.pivot_table(index="device",columns="ip_ver",aggfunc='size',fill_value=0)

device_fig_ip_title = '端末種別比率(v4)'
device_fig_ip = px.pie(data_frame=df_device_ip,
       values=4,
       names=df_device_ip.index,
       hover_name=df_device_ip.index,
       labels={'device':'Device',4:'count'})
device_fig_ip.update_layout(xaxis={'categoryorder':'category ascending'},  title=device_fig_ip_title)
device_fig_ip.update_traces(textinfo='percent+label')
device_fig_ip.show()

device_fig_ip6_title = '端末種別比率(v6)'
device_fig_ip6 = px.pie(data_frame=df_device_ip,
       values=6,
       names=df_device_ip.index,
       hover_name=df_device_ip.index,
       labels={'device':'Device',6:'count'})
device_fig_ip6.update_layout(xaxis={'categoryorder':'category ascending'},  title=device_fig_ip6_title)
device_fig_ip6.update_traces(textinfo='percent+label')
device_fig_ip6.show()

image.png

若干ではありますがIPv4はPCが多く、逆にIPv6ではモバイル端末が多いのが見えてきました。
今回は何で差が出るかまでは調べてないですが、ちょっと気になりますね。

ヒートマップで可視化してみる

次はseabornを使ってヒートマップを見てみます。

時間帯ごとのアクセス数

  • IPv4/IPV6
figure = sns.heatmap(pd.crosstab(df['ip_ver'], df['hour']), fmt="1.1f", lw=0.7, cmap='Blues')

image.png

  • 端末種別ごと
figure = sns.heatmap(pd.crosstab(df['device'], df['hour']), fmt="1.1f", lw=0.7, cmap='Blues')

image.png

ヒートマップもなんとなく特徴が出ました。
・昼間はPCから(社内のアクセスも多いのかな?)
・夜の20-21時は帰宅中の電車でスマホから見てるのかなー
とか思いながらヒートマップを見てみると意外と面白かったです。

参考にしたページ

余談

勉強がてらデータ分析をしてみたところ、若干ですが特徴が見えてきて、いろいろ想像も膨らんで面白かったです。
今後の展開でアクセスログの活用方法として、サービスの障害情報を発信するページへのアクセスログを分析できないかという案が出ました。「アクセス増加」⇒「サービス使えていない人が増加」⇒「サービス障害の可能性」となり、アラームを検知しないサイレント障害の気づきになるのでは…!? と思っていましたが、弊社WEBサイトの更改がありApacheではなくなってしまったので、そちらはまた別途取り組んでいけたらなと思っています。。。

8
4
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
8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?