PythonでApacheのログを読む
PythonでApache(httpd)のログをパースして読んでみます。もっと具体的に言うと、さくらインターネットのレンタルサーバーのログです。
目次
さくらインターネットのレンタルサーバーのApacheの設定
公式サイト に説明があります。公式から引用すると、下記の項目がログに記録されています。記録されたログは、gzip圧縮されて、ログローテーションで古いものから廃棄されます。
アクセス先ドメイン名(※)
アクセス元のホスト名もしくはIPアドレス
クライアント側のユーザ名(通常は空欄)
認証を行った際のユーザ名(通常は空欄)
アクセス日時
クライアントがアクセスした際のリクエスト内容
リクエストに対するステータスコード
実際に転送したデータ量
リファラ(どのリンクから辿ってきたのか)
ユーザエージェント
(※)この項目を保存するかどうかは選択できるのですが、本記事では保存するという前提で記載します。
Pythonでログをパースする
生のログファイルを開けてみると、なにやらデータがスペースで区切って記録されているように見えます。
自力でパースしても良いのですが、 apache_log_parser という便利なモジュールがありますので使わせていただきます。
> pip install apache_log_parser
import apache_log_parser
line_parser = apache_log_parser.make_parser(patern)
ret = line_parser(log)
変数 |
型 |
内容 |
---|---|---|
patern |
str |
Apacheのログフォーマット文字列。 |
log |
str |
Apacheのログの1行分。 |
ret |
dict |
ログをパースした結果。 |
make_parserメソッドにApacheのログファイルのパターン文字列を渡してline_parserオブジェクトを作り、そのパーサーオブジェクトにログを渡します。すると、パースした結果を辞書形式で返します。
では、パターン文字列はどのように指定しましょうか。
Apacheのログ書式は、 こちらのサイト に書き方が書かれています。これをさくらインターネットの公式サイトの説明にあてはめていきます。
これでどうでしょうか。
%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"
試してみましょう。
さくらのレンタルサーバーのウェブサーバーのログファイルから、最初の1行のログをパースして、表示してみます。
import gzip
import apache_log_parser
import pprint
with gzip.open('access_log_20190728.gz', mode='rt') as f:
log_data = f.read().splitlines()
line_parser = apache_log_parser.make_parser('%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"')
pprint.pprint(line_parser(log_data[0]))
出力はこうなります。
{'remote_host': 'xx.xxx.xx.xxx',
'remote_logname': '-',
'remote_user': '-',
'request_first_line': 'GET /rum/post/python_trim_csv_row/ HTTP/1.1',
'request_header_referer': '-',
'request_header_user_agent': 'Mozilla/5.0 (compatible; xxxxxxbot/2.1; '
'+http://www.sample.com/bot.html)',
'request_header_user_agent__browser__family': 'xxxxxbot',
'request_header_user_agent__browser__version_string': '2.1',
'request_header_user_agent__is_mobile': False,
'request_header_user_agent__os__family': 'Other',
'request_header_user_agent__os__version_string': '',
'request_http_ver': '1.1',
'request_method': 'GET',
'request_url': '/rum/post/python_trim_csv_row/',
'request_url_fragment': '',
'request_url_hostname': None,
'request_url_netloc': '',
'request_url_password': None,
'request_url_path': '/rum/post/python_trim_csv_row/',
'request_url_port': None,
'request_url_query': '',
'request_url_query_dict': {},
'request_url_query_list': [],
'request_url_query_simple_dict': {},
'request_url_scheme': '',
'request_url_username': None,
'response_bytes_clf': '39015',
'server_name': 'water2litter.net',
'status': '200',
'time_received': '[28/Jul/2019:00:00:10 +0900]',
'time_received_datetimeobj': datetime.datetime(2019, 7, 28, 0, 0, 10),
'time_received_isoformat': '2019-07-28T00:00:10',
'time_received_tz_datetimeobj': datetime.datetime(2019, 7, 28, 0, 0, 10, tzinfo='0900'),
'time_received_tz_isoformat': '2019-07-28T00:00:10+09:00',
'time_received_utc_datetimeobj': datetime.datetime(2019, 7, 27, 15, 0, 10, tzinfo='0000'),
'time_received_utc_isoformat': '2019-07-27T15:00:10+00:00'}
ボットが来てたみたいですね。
辞書形式のデータが得られますので、その辞書にkeyを指定すればvalueが得られます。
404を返したログを抽出して、この日に何回404を返したか数えてみます。
import gzip
import apache_log_parser
with gzip.open('access_log_20190728.gz', mode='rt') as f:
log_data = f.read().splitlines()
line_parser = apache_log_parser.make_parser('%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"')
logs = []
for i in range(len(log_data)):
log_line_data = line_parser(log_data[i])
logs.append(log_line_data)
not_found = [i for i in logs if i['status'] == '404']
print(len(not_found))
4716
あれ、ずいぶん多い。
公開日
広告
Pythonカテゴリの投稿
- PythonからWindows RuntimeのAPIを使ってみる
- Pythonから外部のアプリケーションを実行する
- PythonでApacheのログを読む
- PythonでURLを結合する
- PythonでURLを解析する
- Pythonでtar.gzなファイルを解凍(展開)する
- Pythonでwavファイルを書き出す
- Pythonでwavファイルを読み込む
- Pythonでデータを整形して出力する
- Pythonでハミング窓関数を作る(SciPy編)
- Pythonでブール値を数値に変換する
- Pythonでモジュールをインポートする
- Pythonで数値を比較する
- Pythonで文字の内容から真偽値の判定をする
- Pythonで自前の関数を定義する
- Pythonで論理演算する
- Pythonのprint関数で改行せずに出力する
- Pythonのプログラムを終了する
- Pythonの関数には参照を渡す
- Windows10 バージョン1703 Creators Update にPythonとSphinxをインストール
- Windwos10 バージョン1703 Creators Update にPythonとSphinxをインストール (Anaconda編)
- reStructuredTextの表
- ダウンロードしたファイルのチェックサムをPythonで確認してみた
- 反復処理 (while)
- 反復処理(for)
- 条件分岐
- 自作のモジュールをインポートする