MTvoteを付けたのは良いのだけれど、 なんだかよくわからない記事にたくさん投票されてます。 アクセスログを見てみると、 どうもクローラー(ボット)からのアクセスが大半らしい・・・
これでは正しい集計ができないので、対策をとってみましょう。 ついでに、 同じ人が同じ記事に一度に何度も投票できないような制限を、 非常に単純な仕掛けでかけてみます。
改造内容はこんな感じにします。
- Google、 Yahoo!、 MSN、 Baidu からのクローラーをアクセス制限
- 同一IPアドレスから同一Entryへの連続投票を制限
すごく手抜きなので、制限事項は下記以外にもたくさんありますw
- IPアドレスとEntry_IDはサーバーで一つしか保持していないので、Aユーザが2回連続投票する間にBユーザが投票してしまうと、Aユーザは連続投票できてしまう。
- 保存ファイルにロックをかけていない(タイミングによっては壊れてしまうかも)
- FORMはGETのみ(POSTに対応させてません)
ほかにもいろいろありますが、ご勘弁を。 まぁ、 使えそうだからいいかな~。
FORMの記述と改造内容は下記のとおり。 なお、下記をもとに改修を行ったことによる如何なる損害についても、 ワタシは責任を負わないものといたしますw。
まずはFORMのほうから。 個別記事のテンプレートに下記のような設定を追加しています。
Bad ← <a href="<$MTCGIPath$>mt-vote.cgi?__mode=vote&entry_id=<$MTEntryID$>&value=1"> 1 </a>
<a href="<$MTCGIPath$>mt-vote.cgi?__mode=vote&entry_id=<$MTEntryID$>&value=2"> 2 </a>
<a href="<$MTCGIPath$>mt-vote.cgi?__mode=vote&entry_id=<$MTEntryID$>&value=3"> 3 </a>
<a href="<$MTCGIPath$>mt-vote.cgi?__mode=vote&entry_id=<$MTEntryID$>&value=4"> 4 </a>
<a href="<$MTCGIPath$>mt-vote.cgi?__mode=vote&entry_id=<$MTEntryID$>&value=5"> 5 </a>
→ Good 平均点:(<MTVoteAverage lastn="300">) 総合点:(<MTVoteTotalValue>) 投票人数:(<MTVoteNumber>)<br />
次に MTVote の改造です。 今回は、 mt-vote.cgi のみの改修となります。 通常は、 $MT_DIR/plugin/ に入れてあるはずです。 内容は下記のとおり。 太字のところが追加になります。
#!/usr/bin/perl -wuse strict;
my($MT_DIR);
BEGIN {
if ($0 =~ m!(.*[/\\])!) {
$MT_DIR = $1;
} else {
$MT_DIR = './';
}
unshift @INC, $MT_DIR . 'lib';
unshift @INC, $MT_DIR . 'extlib';
}
# エラー表示関数
sub error()
{
print "Content-Type: text/html\n\n";
print "<html><head>\n";
print '<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">';
print "</head><body>\n";
print "<strong>$_[0]</strong><br />\n";
print "</body></html>\n";
exit;
}# 前回のIPアドレスとENTRY_IDをファイルから読み込み
my $mtvote_check="./mt-votechk.dat";
open(IN,"$mtvote_check") || &error("Open Error $mtvote_check");
my $rdata = <IN>;
my ($ipaddr, $entry_id) = split(/:/, $rdata);
close(IN);# 主要なBOTを排除
my $uagent = $ENV{'HTTP_USER_AGENT'};
if (($uagent =~ /Googlebot/)||($uagent =~ /Slurp/)||($uagent =~ /msnbot/)||($uagent =~ /Baidu/)){
&error("access denied");
}# FORMからの引数(IPアドレスとENTRY_ID)を取得
my %QUERY;
my $qdata = $ENV{'QUERY_STRING'};
my @qdatas = split(/&/, $qdata);
foreach my $pair (@qdatas) {
$qdata =~ tr/+/ /;
$qdata =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg;
my ($qname, $qvalue) = split(/=/, $pair);
$QUERY{$qname} = $qvalue;
}#ひとつ前とIPアドレス、ENTRY_IDが同じだった場合
if (($ENV{'REMOTE_ADDR'} eq $ipaddr) && ($QUERY{"entry_id"} == $entry_id)) {
&error("すでに投票いただいております。ブラウザの戻るを押してください");
}# 今回のIPアドレスとENTRY_IDをファイルへ保存
open(OUT,">$mtvote_check") || &error("Write Error $mtvote_check");
print OUT "$ENV{'REMOTE_ADDR'}:$QUERY{'entry_id'}";
close(OUT);
eval {
require MT::App::Vote;
my $app = MT::App::Vote->new ( Config => $MT_DIR . 'mt.cfg',
Directory => $MT_DIR )
or die MT::App::Vote->errstr;
local $SIG{__WARN__} = sub { $app->trace ($_[0]) };
$app->run;
};if ($@) {
print "Content-Type: text/html\n\n";
print "An error occurred: $@";
}
次にデータ保存用のファイルを作ります。 Windows では Explorer で新規にテキストファイルを作成し、 名前を mt-votechk.dat にします。 このファイルを、 mt-vote.cgi と同じディレクトリに FTP でアップロードし、 ファイル属性を 0666 に変更します。
最後に、 個別の記事を再構築してあげれば完成です。
これに伴いまして、 MTvote を付け始めてからの投票情報をいったんすべてクリアしました。
削除の仕方はデータベースによって異なると思いますが、 MySQL の場合はこんな感じです。
まず、 phpMyAdmin を起動して、 mt_plugindata テーブルを選択します。 検索タブをクリックし実行ボタンを押してテーブルのレコード一覧を表示させます。 plugindata_plugin の列が 'MTVotingSystem' となっているものをすべてチェックし、 一括削除します。 これでデータがクリアされました。 記事を再構築すればマッサラな状態から集計が始ります。
まだあまり検証できてないので、気づいた点があればご連絡ください^^。





コメントする