はじめに

このメモについて

ログ解析ツールのAWStatsは、見た目がこぎれいなのに加え、ExtraSectionという機能を使えば、ちょっとしたカスタムレポートをコードを一切書かずに実現できたりと、機能的にも充実しています。

このAWStatsのレポートにひとつに「検索文字列」というものがあります。 これは、検索サイト経由でこのサイトにたどり着いたユーザがどのような文字列で検索したのか、その文字列をランキングする機能です。

SEO的に興味深いレポートなのですが、日本語の文字列の場合はいろいろと問題があります。

  • 表示が文字化けする。
  • 同じ見た目の日本語文字列が別々にカウントされている。
  • 2バイト英数字と1バイト英数字の文字列が別々にカウントされている。 「USB」と「USB」など。
  • 2バイトスペースがキーワードの区切りとして認識されていない。

そこでこのメモでは、これらの問題を解消するパッチの導入方法の説明と、このような問題が発生する原因について説明します。

パッチの導入

必要なもの

Jcode.pm
$j->s()が使える新しめのバージョンが必要です。 参考までに、0.88はダメで、2.03は大丈夫です。
v1.1で$j->s()を使わないようにしました。なので古めのJcodeでも動くと思いますが、できるだけ新しいバージョンを使った方がよいと思います。

パッチの適用

私が作ったパッチはAWStatsの古いバージョン用のものです。
新しいAWStats向けのものは、

で公開されていますので、こちらを使った方がいいでしょう。

まずはAWStatsをインストールします。ここではその手順は説明しませんので、AWStatsのサイトのインストール手順などを参照してインストールしてください。

インストールが終わったら、修正パッチをダウンロードします。
「6.5_1.857」は、AWStatsのバージョン6.5 (build 1.857)用であることを意味します。 build番号は、インストールしたAWStatsのレポートページの一番下を見るか、ident awstats.plgrep Revision awstats.plで確認できます。
build番号が違っても、バージョン番号が同じならパッチの適用はできると思います。

name version date size
awstats-6.5_1.857-fix-searchword-3.patch.gz 1.2 2006-05-02 22:48:17 955 byte

パッチをダウンロードしたら、以下のようにawstats.plがあるディレクトリに移動してパッチを適用します。

# cd /usr/local/awstats/wwwroot/cgi-bin
# gzip -cd ~/awstats-6.5_1.857-fix-searchword.patch.gz | patch -p0
patching file awstats.pl

エラーが表示されなければパッチの適用は成功です。

設定の確認

このパッチ特有の設定項目はありませんので、リファレンスマニュアルを見て設定すればよいですし、既存の設定がある場合はそのままでよいです。 ただし、もし$KeyWordsNotSensitive=0にしている場合は1に変更してください(省略時は1です)。1にしていると、アルファベットの大文字小文字を区別するようになるので、「USB」と「usb」が別の単語としてカウントされてしまいます。

動作確認

特に気をつけるべき点はありません。素のAWStatsと同じように実行して、 「検索文字列」が文字化けしていないか確認します。

「検索文字列」の文字化け解消はパッチ適用後に解析した分からになります。 ですので、パッチ適用前のものは依然として文字化けしたままになると思います。 解析対象となるログファイルが残っていて、パッチ適用前のものも文字化け解消したい場合は、DirDataに保存されている解析結果のデータファイルawstatsMMYYYY.FQDN.txtをリネームして、再度、解析実行してください。

ただ、どうしても日本語の自動判別に失敗することがあり、その場合、文字化けすることがあります。

また、日本語処理が増えるので、AWStatsのログ解析時間はパッチ前より(かなり)増えます。

問題の原因

問題の種類と解決方法

前節までで文字化けは解消されたと思うのですが、では、そもそもどのような問題があり、このパッチはどのようにして問題を解消したのか、という点について説明したいと思います。

表示が文字化けする

表示上の文字化けを解消するだけなら、付属のdecodeUTFKeysプラグインで実現できそうなのですが、なかなかそうはいきません。

その理由はこうです。

まず、decodeUTFKeysはEncodeモジュールは文字コードの変換にEncodeモジュールを使っているのですが、入力文字コードはUTF-8だと決めうちしています。 多くの検索サイトの結果表示ページはUTF-8ですが、国産の検索サイトなどでUTF-8ではないサイトもあります。なので入力文字コードの自動判別が必要になってくるのですが、Encodeの自動判別モジュールEncode::Guessは、その判定ロジックのため(コードポイントが同一で本当に自動判別できないとき以外でも)一意な文字コードに判別できないことが多々あります。

ふたつめの問題は、QUERY_STRINGの内容です。 本来なら、URL encodeされた文字列がQUERY_STRINGになるはずなのですが、 IEでアドレスバーに直接入力したときなどはエンコードされないURLで検索サイトにアクセスするようです。しかし気の利いた検索サイトはエンコードされていないQUERY_STRINGもちゃんと処理して検索結果を表示してくれます。
この結果、Webサーバのアクセスログのリファラには、Shift_JISをそのまま含んだURLが記録されます。

さらにWebサーバがApacheの2.0.46以上の場合、もうひとひねりあります。

Apache 2.0.46から、印字不可能文字をログに記録するときは「\xHH」の形式にエスケープするようになりました。なのでリファラにShift_JISなどが含まれる場合は、この形式にエスケープされた形で記録されます。

そして最後の問題です。 AWStatsはデフォルトで検索文字列の大文字小文字を無視してカウントしようとし、そのためアルファベットをlcという関数で小文字に変換してからカウントします。

この小文字化の処理の何が問題かというと、 例えばShift_JISの「ア」(0x8341)をlcにかけると「ヂ」(0x8361)になってしまいます。 これはlcはマルチバイトを意識しないため、「A」(0x41)を「a」(0x61)に変換してしまうためです。

この3つの問題を解決するために、このパッチでは次のようにしています。 処理のタイミングはリファラのデータを処理するところです。

  • 「\xHH」の形式を元に戻す。
  • 入力文字コードを自動判別して、UTF-8に変換する。 自動判別には、Encode::GuessではなくJcodeを使う。
  • URL encodeしなおしてからlcで小文字化する。

同じ見た目の文字列なのに、別々にカウントされている

検索文字列レポートで、表示上は同じ文字列なのに別々にカウントされることがあります。この原因はこうです。

AWStatsは検索文字列をURL encodeされた状態でカウントし、その結果を保存しています。ということは、例えば同じ「いろり」という文字列でも、その文字コードがEUC-JPとShift_JISとではコードポイントが異なるのでAWStatsは異なる文字列と認識してしまいます。

そこでこのパッチでは次のようにして解決しています。

  • すべての文字列について、いったん各種デコードしてUTF-8への変換とURL encodeをしなおす。 以降の処理ではこのURL encodeした文字列を使う。

2バイト英数字と1バイト英数字が別々にカウントされている

これはもうそのままです。 日本語特有の処理なのでしかたないですね。 意味的に同じな「USB」と「USB」は同じ単語としてカウントして欲しいので、このパッチでは次のようにしています。

  • マルチバイトのA-Za-z0-9を1バイトの文字に変換する。

2バイトスペースがキーワードの区切り文字として認識されない

これも日本語特有の問題ですね。 AWStatsはスペースをキーワードの区切りとして認識するので、 このパッチでは次のようにしています。

  • マルチバイトのスペースを1バイトのスペースに変換する。

変更履歴

2006-05-02
v1.2を公開。
検索文字列に%0Dや%0Aが含まれていると、データファイルのKEYWORDセクションが壊れてしまう問題に対応。
2006-03-15
v1.1を公開。
$j->s()を使わないようにした。
2006-02-26
初版公開。

目次