このブログを検索

2011/10/08

アクセスログ解析スクリプトの改善

アクセスログ解析スクリプト、改善した。
#! /usr/bin/perl

use strict;
use URI::Escape;
use Encode;
use DateTime;
use utf8;

my @line;
my @line2;
my @line3;
my $useragent;
my $unescaped;
my $print_level = 2;

sub print_selected{
    my ($date, $time, $host, $addr, $search_engine,
    $search_string,$useragent,$browser,$misc)=@_;

    print '<font face="georgia" size=-2><br></font>';
    print '<b>'.$search_string.'</b><br>';
    print '<font face="georgia" size=-2>';

    if($search_engine=~ /Google/){
        print ' <font color="navy"><b>'.$search_engine.'</b></font>';
    }elsif($search_engine=~ /Yahoo/){
        print ' <font color="red"><b>'.$search_engine.'</b></font>';
    }elsif($search_engine=~ /Baidu/){
        print ' <font color="orange"><b>'.$search_engine.'</b></font>';
    }else{
        print ' <font color="black"><b>'.$search_engine.'</b></font>';
    }
    $time =~ s/\[//g;
    print '<br><br></font>'."\n";
}

my $date = DateTime->now( time_zone => 'Asia/Tokyo' )->subtract(days=>1);
my $logfilename;

if($#ARGV >=0){
    my $test='cp ../../log/access_log_'.$ARGV[0].'.gz ../../log/tmp';
    system($test);

    $test='gunzip -f ../../log/tmp/*.gz';
    system($test);

    $test='mv ../../log/tmp/access_log_'.$ARGV[0].' ../../log/tmp/log.txt';
    system($test);

    $logfilename='../../log/tmp/log.txt';
}else{
    $logfilename='log.txt';
}

print "Content-type: text/html\n\n";
print "<html><head>\n";
print '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">';
print "<title>Searched Strings</title>\n";
print '
<style type="text/css">
<!--
BODY, TH, TD { font-family: "Osaka"; }
-->
</style>

'."\n";
print "</head>\n";

print "<body>\n";
#print "<a href=\"$logfilename\">$logfilename<\/a>  ";
#print "<br>print level:".$print_level."<br>";

print "<blockquote>\n";

open LOG,"<$logfilename" or die;

while(<LOG>){

    if(/googlebot\.com|Baiduspider/){
        if ($print_level > 1) {
            next;
        }
    }else{
        print "<br>";
    }

    print '<font face="georgia" size=-2>';
    print;
    print '</font>';

    @line=split;

    if(/.+(\(.+\))/){
        $useragent=$1;
    }

    if(/google/){
        @line2 = split /&q=|\?q=/, $_;
        @line3 = split /&/, $line2[1];

        $unescaped = uri_unescape($line3[0]);

        if($_ =~ /ie=SJIS/){
            $unescaped = Encode::decode('shiftjis',$unescaped);
        }

        $unescaped =~ s/\+/ /g;
        &print_selected(@line[0],@line[1],@line[2],@line[3],
        "Google",$unescaped,$useragent);

    }elsif(/yahoo.+search\?/){
        @line2 = split /p=/, $_;
        @line3 = split /&/, $line2[1];
        $unescaped = uri_unescape($line3[0]);
        $unescaped =~ s/\+/ /g;
        &print_selected(@line[0],@line[1],@line[2],@line[3],
        "Yahoo",$unescaped,$useragent);

    }elsif(/yahoofs.+search/){
        @line2 = split /p=/, $_;
        @line3 = split /&/, $line2[1];
        $unescaped = uri_unescape($line3[0]);
        $unescaped =~ s/\+/ /g;
        &print_selected(@line[0],@line[1],@line[2],@line[3],
        "Yahoofs",$unescaped,$useragent);

    }elsif(/baidu.jp\/s\?/){
        @line2 = split /wd=/, $_;
        @line3 = split /&/, $line2[1];
        $unescaped = uri_unescape($line3[0]);
        $unescaped =~ s/\+/ /g;
        &print_selected(@line[0],@line[1],@line[2],@line[3],
        "Baidu",$unescaped,$useragent);

    }elsif(/bing.+search/){
        @line2 = split /q=/, $_;
        @line3 = split /&/, $line2[1];
        $unescaped = uri_unescape($line3[0]);
        $unescaped =~ s/\+/ /g;
        &print_selected(@line[0],@line[1],@line[2],@line[3],
        "bing",$unescaped,$useragent);

    }elsif(/biglobe.+search/){
        @line2 = split /q=/, $_;
        @line3 = split /&/, $line2[1];
        $unescaped = uri_unescape($line3[0]);
        $unescaped =~ s/\+/ /g;
        &print_selected(@line[0],@line[1],@line[2],@line[3],
        "biglobe",$unescaped,$useragent);

    }elsif(/search\.goo\.ne\.jp/){
        @line2 = split /MT=/, $_;
        @line3 = split /&/, $line2[1];
        $unescaped = uri_unescape($line3[0]);
        Encode::from_to($unescaped, 'euc-jp','utf8');
        $unescaped =~ s/\+/ /g;
        &print_selected(@line[0],@line[1],@line[2],@line[3],
        "goo",$unescaped,$useragent);

    }else{
        print "<br>\n";
    }
}

close(LOG);

print "</blockquote></body></html>\n";
検索エンジンごとに個別にやっているところは、本当はまとめてしまいたいところなのだが、とりあえずはこれで。 これでもずいぶんすっきりした。

googleで、url(uri?)デコードしたした後に文字バケしたことがあった。 URLデコードのできるページで同じ文字列をデコードするとちゃんと表示される。shift-jisとかutf-8とかを判定してどのコードでも表示できるようにしているのだろう。どうやっているのかはわからない。 ログをよく見ると、

&ie=SJIS&oe=SJIS
というパラメータがついている。どういう場合にこうなるのかわからないが、あまりないので、この文字列があったら shift-jisをデコードするようにした。 最初は from_to で shiftjis から utf8 に変換したのだがなぜかうまくいかないので decode を使った。 Encodeの動作がイマイチよくわからない・・・

log解析スクリプトは、最新を上に表示したいので、print reverseを使ってログをひっくり返してから読むようにした。 そのときちょっとはまったのは、最初に

open FILE,">filename.txt";


とやって書き出すのはできるんだけど、その後にもういちどそこに書き込めないこと。 ファイルが開けない。 属性を書き換えていけたんだけど。 どうして一発目はかけるのに、その後はダメなんだろう?

perlのハナシじゃないんだけど、iPhoneでこのページを見ると字が小さすぎてしまう。useragentを見てページを作り分けるなんてことは面倒だしもっと簡単な方法があるだろうと調べた。以下のようにする。

print '<link href="../../css/bbz.css" type="text/css" rel="stylesheet">';
print '<link media="only screen and (max-device-width:480px)" href="/css/bbziphone.css" type="text/css" rel="stylesheet"/>';
print '<meta name="viewport" content="width=320, initial-scale=1.0, maximum-scale=1.0, user-scalable=no /">';


最初の行は、今まで書いてあった cssファイルを指定していたもの。その後の2行を足す。そして bbziphone.css に、iPhone用のスタイルを書く。とりあえずこれでできたけど、普通のと、iPhone用とほとんど同じで一部だけ違うっていうのが、ちょっとイヤだな。cssファイル内部でなんとかできないものかな?