このエントリーをはてなブックマークに追加

Apache logをparseする

この記事はPython Advent Calendar 2013の12日目です。

named tupleについて書こうとしたのですが、ぐぐってみると昨年度のAdvent Calendarで書かれていました。うう、気がついていなくてすいません。

というところで、カスタマイズ済みのApacheログ書式もパースするApache::Log::Parser の話という記事を目にし、恐れ多くもpythonの場合を書いてみたいと思います。

え、「今年はWeb以外じゃなかったっけ?」だって?

あーあーあー聞こえないー。い、いや、厳密にはwebじゃないもん。ないもん…

apachelog

pypiには

の2種類が上がっています。

apache-log-parserの方が更新は新しいのですが、ドキュメントもなくフォーマットも自由度が高くないので、apachelogの方を使います。

% pip install apachelog

でインストールは完了です。

使い方

基本的な使い方はparserを作ってparseするだけです。

p = apachelog.parser(format)  # formatは後述

for line in open('access.log'):
    data = p.parse(line)

apachelogのいいところは、フォーマットが自由というところです。

こう書くと「え、正規表現を自分で書くの?」と思われるかもしれませんが、apachelogはapacheのconfigに書いたフォーマットをコピーすればそれでちゃんとparseしてくれます。

つまり、例えば httpd.confにこう書いてあったとすると、

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""

pythonコードとしてこう書けばいいわけです。

format = r'%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"'

簡単ですね。また、よく使われる以下の3つについてはフォーマットが事前に定義されています。

# Common Log Format (CLF)
p = apachelog.parser(apachlog.formats['common'])

# Common Log Format with Virtual Host
p = apachelog.parser(apachlog.formats['vhcommon'])

# NCSA extended/combined log format
p = apachelog.parser(apachlog.formats['extended'])

注意点

注意点が一つあります。parseして出てきたデータですが、辞書形式になっています。

なっていますが、keyがフォーマットの文字列そのままになります。つまり、こんな感じです。

>>> data = p.parse(line)
>>> pprint(data)
{'%>s': '200',
 '%D': '275',
 '%H': 'HTTP/1.1',
 '%I': '704',
 '%O': '272',
 '%U%q': '/index.html',
 '%b': '43',
 '%h': '192.168.1.110',
 '%m': 'GET',
 '%t': '[11/Dec/2013:00:00:00 +0900]',
 '%{Referer}i': '',
 '%{User-Agent}i': 'Mozilla/5.0 (Linux; U; Android 2.3.5; ja-jp; Build/145.0.0002) '}

ちょっと分かりにくいですね。

まとめ

apacheのlogをparseをしてくれるapachelogを紹介しました。フォーマットの自由度が高く、かつ、単にコピーすればいいという手軽さはとても重宝します。

え、速度?あー、測ってなかったですね、そういえば。まあ、遅くはないんじゃないですかね。うん。

そんな感じでお茶を濁してみました。

追伸

みなさんは携帯をいつなくしても困らないようにリモートにバックアップと、AndroidLostのようなツールを入れておきましょう。

かなり凹みます。

ほんとに。