Perl/CGI研究室 'PERL-LABO'

Perl/CGI研究室 'PERL-LABO' TOPへ
戻る(History.Back)

リファラーをまとめる

研究内容

同じサイトの複数のページからリンクしてもらっているとき、 それらのリンクからの訪問を全てまとめてカウントして、 1つのサイトからの訪問であるとして表示する方法を考えます。

詳細

"ページ"ランキングから、"サイト"ランキングへ

リファラーによってリンク元のウェブページを知ることができるのは分かりました。 これによってリンク元の"ページ"ランキングを作ることができました。 しかし、同じサイトの複数のページからリンクしてもらっている場合、 それぞれのウェブページが別々にカウントされてしまうので、ちょっと不便です。 ブログなど、リンクが全てのページに掲載されるようなサイトからの訪問を正しく処理できません。 また、"http://domain.com/" と "http://domain.com/index.htm" が別々にカウントされて しまうといった問題もあったのでした。 そこで、それらを同じサイトからの訪問をまとめてカウントして、 "ページ"ランキングから、"サイト"ランキングへ改良してみようというのが 今回の研究です。

したいことを具体的に書くと

リファラーランキングはURLをデータとして扱っていました。 で、やりたいことは具体的には、

 http://www.hogehoge.jp/
 http://www.hogehoge.jp/index.html
 http://www.hogehoge.jp/link/

といったURLからの訪問を、全部まとめて

 http://www.hogehoge.jp/

からの訪問として処理しよう、ということです。

まとめるタイミングについて

これを実現する際の処理のタイミングですが、考えてみると2つあるようです。 1つは、リファラーカウンターにアクセスがあった時点でこの「まとめる処理」をして、 まとめてからデータファイルに書き込むという方法。 もう1つは、データファイルへの書き込みは今まで通りそれぞれのURLのまま行って、 表示するときにまとめる処理を行うというものです。

この2つ、結果は同じでもいくつかの点で違いがあります。 保存されるデータが「生」か「加工後」かという点も大きな違いです。 「生」と「加工後」というデータの違いは、場合によっては重要かも知れません。 でも、今はそれほど気になりませんね。 それより、負荷の違いが気になります。 サーバーに加わる負荷は、どちらの方が軽いでしょうか? ランキングを表示する回数にもよりますが、現在のところはこのリファラーカウンターは 時々サイトの管理者が参考にするといった使い方を想定していますので、 ランキング表示する回数はあんまり多くないです。 やり方が複数あるとき、負荷が軽い方を選ぶというのは良い方法の1つですよね。 ですから、まとめる処理はランキング表示するときに行うことにしました。

どこがトップページか?

URLを1つにまとめる具体的な処理ですが、 ランキング表示する際に、前処理として 「サイトのトップページより下の階層のページ(サブページ)については、 訪問カウントをそのサイトのトップページURLに加えて、 サブページのデータは削除する」ということをすれば良さそうです。 例えば、URLと訪問カウントが次のようになっていたら、

 47 http://www.uhehe.jp/
 37 http://www.hogehoge.jp/
 15 http://www.hogehoge.jp/link/

前処理して、次のような状態になってから、ランキング画面を表示します。(順位逆転!)

 52 http://www.hogehoge.jp/
 47 http://www.uhehe.jp/

ここで問題なのは、「どこがトップページのURLなの?」ということですね。 ここでは、http://www.hogehoge.jp/link/http://www.hogehoge.jp/の中のリンクページだと仮定してまとめちゃいましたが、 本当は別のサイトかも知れません。機械的には判断できないです。 ということで、「どこがトップページか?」という情報は、CGIプログラムに教えてあげる必要があります。

そこで、どのようなデータを与えるかということを考えてみます。 ここまでの内容を考えると、「サイトのトップページのURL」があればサブページのカウントを トップページに加えるという処理はできそうです。 これは、普通はサブページのURLはトップページのURLを 含むからです。(サブページのURL=トップページのURL+なにか文字列。) しかし、サブページが別のドメインになっているようなサイトもあるかも知れませんよね。 そういったケースにも対応できるようにするため、

 文字列1<>URL1
 文字列2<>URL2
 …

というデータファイルを用意することにしましょう。 連想配列形式のデータになっていますね。 このデータを読んで、 URLの中に 文字列1 が含まれているとき、そのURLを URL1 に変換して処理する、ということにします。 上の例だと、

 http://www.hogehoge.jp/<>http://www.hogehoge.jp/
 http://www.uhehe.jp/<>http://www.uhehe.jp/

というデータがあれば、それぞれのサブページは全てトップページに変換されます。 別ドメインにサブページがあるケースとしては、例えばuhehe.jpというサイトのサブコンテンツがuhoho.jpにあったら、

 http://www.hogehoge.jp/<>http://www.hogehoge.jp/
 http://www.uhehe.jp/<>http://www.uhehe.jp/
 http://www.uhoho.jp/<>http://www.uhehe.jp/

とすれば、uhoho.jpからのアクセスもuhehe.jpにまとめることができます。バッチリ!

データファイルの編集機能は…

この、URLの変換規則を表したデータファイルは、とりあえず手作業で作ってアップロードすることにします… データファイルの編集をブラウザ上でできるようにする研究は、次の機会に。

結果

具体的な実装

上に書いた通り、まとめる処理はランキング表示のときに行います。 ランキングの表示は、counters.plというライブラリの中で行うのでした。 変更は、counters.plに対して行います。

加える処理は、次の通り

 1. ランキング表示関数に引数でデータファイル名を渡す
 2. データファイルを連想配列に読み込む
 3. ランキングデータを読み込んだら、ランキングデータをループしてデータの置換処理

これまでの知識で充分できる内容でした。具体的には、次のコードで全部です。 この部分だけコードを抜き出しても意味は分からないですが、この程度の処理でできたという意味で、 ご参考までに…

if ($urlmapfname ne "") {
  my %urlmap = plab::readhashfile($urlmapfname);	# データを読みます
  my @urlparts = keys(%urlmap);      		# 読んだデータの、左側(変換元URL)部分
  my @urls = keys(%data);        		# カウントされているURL
  foreach my $url (@urls) {        		# カウントされているURL全てで
    foreach my $urlpart (@urlparts) {    	# 読み込んだ変換元URL全てで
      if (index($key, $keypart) != -1) {  	# 変換元URLが含まれているか?
        my $newkey = $maphash{$keypart};
        if ($newkey ne $key) {    	# 変換元と変換後は違うものか?
          $data{$urlmap{$urlpart}} += $data{$url}; # 変換後URLにカウントを加えて
          delete($data{$url});  		# このURLは削除します
        }
        last;      			# ループを抜けます
      }
    }
  }
}

実行結果

検索エンジンからのアクセスを1つにまとめた、 当サイトのリファラーランキングです。次のリンクをクリックしてみてください。

PERL-LABO リファラーランキング (2004/12/24〜2006/11/02のデータになります。)

次のデータファイルを使っています。

.google.<>http://www.google.co.jp/
http://72.14.253.104/<>http://www.google.co.jp/
search.yahoo.co.jp<>http://search.yahoo.co.jp/
yahoofs.jp/search/cache<>http://search.yahoo.co.jp/
search.msn.co.jp<>http://search.msn.co.jp/

改良前はこちらです。よかったら比べてみてください。PERL-LABO リファラーランキング

考察

動きました

このサイトは、検索エンジンからの訪問が多いのですが、これで、 同じ検索エンジンなのにURLが違うものを1つにまとめることができて、リファラーランキングがだいぶ見やすくなりそうです。 たくさんの相互リンクをしているサイトさんなどでは、この機能は必須ですよね。

さて最後に、今回、改良をしていて思ったこと。「2重ループだなぁ…」です。 2重ループというのは、処理するデータが多くなるとすごく処理回数が増えてしまうので負荷が怖いですね。 もっといいアルゴリズムは無いかな?

Perl/CGI研究室 'PERL-LABO' TOPへ
戻る(History.Back)

Copyright (c) 'PERL-LABO' All Rights Reserved.  リンクフリーです。