アクセスログからドメインだけを取り出す
うちではクライアントからのウェブアクセスは全部Squidを使ったプロクシを通しています。このアクセスログからドメインだけを抽出して、統計をとりたいんだと。つまり、
- d.hatena.ne.jp
- b.hatena.ne.jp
- hoge.hatena.ne.jp
って3つログがあったら、hatena.ne.jpの部分だけ取り出したいとのこと。はいはいと二つ返事で引き受けたのはいいが、ちょっと大変だった。アクセスログからアクセスURLを取り出すところとか、URLからホスト名(www.hogehoge.comみたいな部分)を取り出すところまでは正規表現ですらすらっと(実は悩みながら)書けたんだけど、その後なやみました。ドットで区切られた後ろ三つ(co.jp,ne.jpの場合),後ろ二つ(.comとか.net)とかってどうやって取り出せばいいんだろう。結局こんなコードになりました。
#!/usr/bin/perl while(<>){ my @fields = split(' ',$_) ; my $url = $fields[6]; if ($url =~ m{^http://([^/:]+(:(\d+))?)(/.*)?$}i){ my $host = $1; my @strings = split('\.',$host); my @rev_strings = reverse @strings; if( $host =~ /[.co.jp|.go.jp|.ne.jp]$/ ){ print ".",$rev_strings[2],".",$rev_strings[1],".",$rev_strings[0],"\n"; } elsif ($host =~ /[com|net|.jp|org]$/ ){ print ".",$rev_strings[1],".",$rev_strings[0],"\n"; } } }
Squidの標準ログだとURLは6カラム目。host名を取り出すところでポート番号とかパスとかを取り出しているのはからのパクリ。そのあと$hostを.でsplitして、reverseして、最後にくっついているTLDによって最後から3つとるか、2つとるかを分岐。正確にやるのなら、もっと条件をきちんと整理しないといけないんだろうけど、それほどデータに精密性が求められるわけではないのでこんなところで。これで標準出力に吐き出してsort -uとかに喰わせればリスト出来上がり。
$ ./script.pl access.log | sort -u > list.log