Referer文字列からロボットかどうかを判定する正規表現

Apacheなどのウェブサーバのアクセスログで、Refererフィールドに出力される文字列が以下のファイルの正規表現のいずれかにマッチするようなら大体それはロボットのアクセスです。

robot_patterns(UNIXテキストファイル)(2010-4-26改訂)

これを使ってApacheのアクセスログからロボットのアクセスを抽出するフィルタの例は以下のとおり。上の内容がrobot_patternsというファイルとしてカレントディレクトリに保存されていると想定してあります。また、Parse::AccessLogEntryが必要ですのでCPANからインストールしておいてください。


#!/usr/bin/perl

use Parse::AccessLogEntry;

$robot_patterns_file = "robot_patterns";
$local_address_patterns_file = "local_address_patterns";

open(RP, $robot_patterns_file) or die $!;
while(<RP>) { chomp; push(@robot_patterns, $_) if ! /^\s+$/; }
$robot_pattern = "(?:" . join(")|(?:", @robot_patterns) . ")";

open(LP, $local_address_patterns_file) or die $!;
while(<LP>) { chomp;push(@local_address_patterns, $_) if ! /^\s+$/; }
$local_address_pattern = "(?:" . join(")|(?:", @local_address_patterns) . ")";

$P = Parse::AccessLogEntry->new();
($myname) = $0 =~ /([^\/]+)$/;

if ($myname eq 'robotsalog') {
        LINE: while(<>) {
                my $e = $P->parse($_);
                next LINE if $e->{host} =~ m/$local_address_pattern/o;
                print if $e->{agent} =~ m/$robot_pattern/o;
        }
} else {
        LINE2: while(<>) {
                my $e = $P->parse($_);
                next LINE2 if $e->{host} =~ m/$local_address_pattern/o;
                print if $e->{agent} !~ m/$robot_pattern/o;
        }
}

robotsalogという名前で呼び出されたときは、ロボットのアクセスだけを出力します。その他の場合はロボットでないアクセスだけを出力します。

ちなみにlocal_address_patternsというファイルも必要です。この中身には自分自身のアドレスのパターンを入れておきます。そうするとその分も除外して出力します。サンプルは以下のとおり。


^192\.168
^127\.0\.


うちではこれで大体うまくいってます。完全無保証でよろしければご自由にお使い下さい。