スパムコメントが3日で1万件以上…

開設より5年近くなる当サイトだが、ここのところこれまでに無かった頻度でスパムコメントが付くようになり、その処理に手こずらされている。

前回の投稿で紹介したように、スパムコメント対策としては、場合により有料となってしまうWordPress推奨のプラグインAkismetではなく、Spammer Blockerというプラグインを入れて対策をとっている。このプラグインはスパムコメントのブラックリストを作成し、同じコメント元からのコメントをブロックしてくれるというものだが、こうした仕組みを導入してなお、リストをかいくぐって悪質な宣伝コメントが付くのだ。その数、3日で11000件。
コメントのほとんどが似たような文章で偽ブランド品の販売業者のリンクを貼ったものであり、ただコメントの発信元のIPはそれぞれ異なっているのでたちが悪い。リストの意味も無くなってくる。

一応、WordPress側の標準機能としてコメントのフィルタリングも可能になっている。たとえば特定単語を含んだコメントを表示しない、リンクを含むコメントを非表示、ユーザ登録しないとコメントを受け付けない、そもそもコメント自体を受け付けないなど。

いずれの解決法も決定的ではない。記事に対する意見のコメントなどを見落とさず、かつスパムによる支障のないブログ運営が出来る方法を探さなければならない。

まあ、近頃更新が滞っていたのはまたそれとは別の理由。


WordPressのスパムコメント対策 Spammer Blocker

WordPressのブログを長く運営していると、投稿に対して無関係なスパムコメントが大量につくようになる。その数たるや、当ブログのような零細ブログであっても1日に数十件、多い時は100件を超える程になる。
これらのスパムコメントを、コメント欄に無条件に表示するようにしてしまっていては、ブログの訪問者に管理されていないサイトであるとの印象を与えるし、また検索エンジンからもスパムリンクを放置しているサイトということで、低い評価をもらってしまう。つまりSEO的にもかなり問題がある。
そこで、コメントはまず承認制にして、スパムコメントでないコメントを管理者のチェックにより表示させるようにしなければならない。でも、日に100件のコメントをいちいちチェックするのは面倒極まりない。

標準でついてくるAkismetプラグイン

WordPressの配布元もスパムコメントの問題については把握しており、いちいち人間の目を通してスパムチェックを行わなくても良いように、自動判別してくれるプラグインが付属している。それがAkismetで、ダッシュボードのプラグイン>インストール済みプラグインから勝手にインストールされていることが確認できる。
Akismetを有効にするには、インストール済みプラグインから有効化を選ぶだけでは不十分だ。Akismet API keyというものを、リンクから飛んで取得しないと行けない。そして(一応申告制なのでごまかせるのかもしれないが)ビジネスユースの場合には有料でキーを取得しなければならない。ということで、運営ブログがビジネスユースなのかそうでないのか判別がつきにくいケースなどでは、有料プランにするべきか不明瞭なこともあり、どうも導入に消極的になってしまう。

特定IPからのコメントをスパム判定する

そこで、Akismetを導入しないでもスパムチェックの手間を省く方法を考える。一日に100件のスパムコメントの中には、似たような内容のものが多いということに気付くだろう。実際、コメント元のIPアドレスは100種類も無く、同一IPアドレスからのスパム投稿が多い。つまり、IPアドレスのブラックリストを作ってしまい、リストに当てはまる投稿者のコメントをスパムに振り分けるようにしてしまえば良いのである。

特定IPをブラックリストに放り込むには、ダッシュボードの設定>ディスカッションでディスカッション設定のページに移動、コメントブラックリストという入力フィールドにIPアドレスを列挙すれば良い。単語の一致でも指定できるので、スパムコメントにありがちなブランド名等でもフィルタリングが行える。

コメントブラックリスト

コメントブラックリスト

IPアドレスは、スパムコメントの下に書いてある、192.168.0.0のような数字である。ただ、これをいちいち控えて、ブラックリストに加えて…という作業は面倒臭い。

Spammer Blockerプラグインを使う

そこで、コメントの一覧からスパム認定を行ったコメントのIPを自動で記録し、次回以降そのIPからのコメントはブロックするという挙動のプラグイン、Spammer Blockerを使うと便利である。
インストールはダッシュボード>プラグイン>新規追加から行えばよい。
インストールして有効化すると、一度スパム認定を行ったIPからのコメントをブロックする。スパム認定を行うわけではなく、そもそも投稿自体をブロックするので、スパムコメントがデータベース上に増えていくこともない。

なお、このSpammer BlockerによってブロックされているIPは、前段で説明したコメントブラックリストに蓄積される訳ではなく、独自のデータベースに貯まっていくことになる。ダッシュボード>設定>Spammer Blockerから設定画面が見られるが、Banned IP addressというセクションに一覧があるので、スパム認定の解除や管理などはここで行えば良い。

このプラグインを導入してからというものの、スパムコメントが多くても1日5件くらいまでに抑えられるようになった。つまり、1日5件くらいまでは新しいアドレスからスパムが来ていたということになるのだが、完璧なブロックを志すなら、コメントブラックリストやAkismetと組み合わせて対処するしかないのだろう。


Conceptual:シンプルなPHP製EXIF表示サービスEXIFviewerを公開

わけあって写真の位置情報なんかを弄るプログラムが必要になって、EXIFについて調べ直している。

調べ直しているというのは、以前に一度PHPにおけるEXIFの扱いなどについて調べていて、DamniPhoneEXIFという誰も得しないWEBサービスに応用したことがあるからだ。DamniPhoneEXIFはPHP標準のEXIFクラスを使わずに、PELというライブラリを使っている。PELを使わないとEXIFデータの書き込みが出来ないためであるが、初期のiPhone3Gで起こる位置情報の経度の東西が逆転するバグを解決するためだけのサービスとして作ったので、そこから色々な機能を建て増していくには不適当だった。それなら単純に標準のクラスでEXIF表示するサービスから作り直そう、ということでEXIFviewerを作った。

キモは、ユーザのローカルファイルを一旦HTML5のDataURLで受けているため、サーバに画像のコピーを作らずに画面リロード後の確認用画像の表示が出来ているというところ。これはOnlyCSViewでもやっていたことなので、詳しいやり方についてはOnlyCSViewの作成エントリを参照してほしい。

ところでEXIF形式って何?

EXIF形式というのは、JPEGやTIFFなどの画像ファイルに画像についての情報を付与してまとめたデータ形式だ。デジカメメーカーが主体となって、写真の撮影状況(撮影日、しぼり、感度、位置情報etc)のデータを画像に埋め込めるようにしたもの。正確に言うと、埋め込むわけではなく新たなファイル形式の大括りを作って、そこに画像の情報と当の画像ファイルをパッケージ化する。そのようにして出来たファイルの拡張子は.jpgや.tiffそのままなので、一見するとEXIFの情報が入ったファイルとの区別がつかない。かくして、デジカメユーザは知らず知らずに、EXIF形式のお世話になっている場合が多い。
ではどのように情報を格納するかというと、TIFF形式以来のファイル先頭へのタグ付けにより、情報を格納している。まずTIFFという名前が、(Tagged Image File Format)の略であり、この形式が登場したことにより、画像ファイルに画像の情報を入れられるようになった。JPEGファイルは同様のタグ付け形式のJFIFというフォーマットをほぼ標準としており、このJFIFをもっと大げさにしたものがEXIFというわけだ。

EXIF形式の構造 ざっくばらんに

つまり、EXIFはTIFFの落とし子だ。ファイルのバイナリデータの一番最初には、TIFFヘッダと呼ばれる8バイトのデータがある。この8バイトのデータのうち4バイトは、次のまとまりへの参照(ファイルの頭からの距離)を格納している。このように、ひとまとまりの情報の中に、他のまとまりの場所情報をセットで含んでいるのが、TIFF形式の特徴だ。
EXIFにどんなまとまりがあるかというと、IFD(Image File Directory)という名前のまとまりがあり、そのまとまりの中にさらに複数の情報がぎっしり詰まっている。
IFDの中にはEXIF IFDというものや、GPS IFDというものがあり、EXIF情報をいただきたい場合この場所にアクセスして情報を見る必要があるわけです。ややこしいね。

PHPのEXIFクラスでのアクセス

先程紹介したPelでは、イメージファイルをコンストラクタに与えて、ゲッターメソッドで一つ一つのまとまりの鍵を開けてアクセスしなければならない。DamniPhoneEXIFでGPSの東西を変えるだけでも、こんなに入れ子のプログラムができてしまった。

<?php
require_once('PelJpeg.php');
if(!empty($_POST["path"])){
$pj = new PelJpeg($_POST["path"]);
if($pjexif = $pj->getExif()){
if($pjtiff = $pjexif->getTiff()){
if($pjifd = $pjtiff->getIfd()){
if($pjgps = $pjifd->getSubIfd(PelIfd::GPS)){
if($gpsarray = $pjgps->getEntries()){
if(isset($gpsarray[3]) && isset($gpsarray[4])){
if(($gpsarray[4]->getText()) == "W"){
$gpsarray[3]->setText("E");
echo "converted west to east.<br>";
}
else if(($gpsarray[3]->getText()) == "E"){
$gpsarray[3]->setValue("W");
echo "converted east to west.<br>";
}
}
}
}
}
}
}
}
?>

PHPのexif_read_data関数では、引数にまず欲しいデータより上位のまとまりを指定して、ごっそりまとまりを取得した後には、foreachや添字でアクセスできる。

exif_read_data(ファイル名,
セクション名(省略化、複数の場合カンマ区切り),
配列で取得するかフラグ(省略可、デフォルトfalse,
サムネイル取るかフラグ(省略化、デフォルトfalse)

とりあえず今回のヴァージョンでは全部表に吐き出してしまっている。

<?php
if(!empty($_POST["path"])){
if($exif = exif_read_data($_POST["path"],NULL,true)){
echo "<table class='exiftable table table-striped'><thead><tr><th>キー名</th><th>値</th></tr></thead><tbody>";
foreach ($exif as $key => $section) {
    foreach ($section as $name => $val) {
	if(is_array($val)){
	foreach ($val as $valname => $vval) {
	echo "<tr><td>$key $name $valname</td><td>$vval</td></tr>";
	}
	} else {
	echo "<tr><td>$key $name</td><td>$val</td></tr>";
	}
    }
}
echo "</tbody></table>";
} else {
echo "画像のEXIFデータが見つかりませんでした。";
}
} else {
echo "画像をセットして下さい。";
}
?>

php.netの説明によると、exif_read_data関数の第一引数にはURL形式は与えられないとのこと。けれども試してみたら、普通に外部サイトの画像URLを与えても表示できた。そこで、$_POST[“path”]にはDataURLを与えることにする。画像のセットで起動して、jQueryでフィールドにエンコードしたURLを入れておくだけ。

外部サイトの画像URLが参照できるというのは面白いので、サービスとして機能を増やせる余地がありそうだ。浮気のアリバイ調査に使えますね。


Conceptual:OnlyCSViewに、ただ何となくBootstrapを適用

ユーザが指定したCSVファイルを表形式でAjax表示するだけのWEBサービス、OnlyCSView。作成して以来、大して弄ることも無く放置していたのだが、Twitter Bootstrapの雰囲気を掴むために、インターフェースだけ変更しようと思い、手入れをした。

そもよ、Twitter Bootstrapって何?

Twitter BootstrapというのはCSSフレームワークの一つで、かのTwitterが提供する無償フレームワーク。これを使えば、簡単にカラムレイアウトが実現できたり、レスポンシブデザインに対応できたり、Twitterのサービスで使っているようなGUI部品が要素へのクラス指定だけで実現できたり…とそこそこ楽しめる。CSSコーダなど、WEBデザイン・レイアウト方面の方々に知名度はある技術だと思うけど、生粋のWEBプログラマでは、Bootstrapの存在を知らないという場合も多い。

どういう部品が使えるのか、どういう機能が付けられるかについては、こちらのデモページが大変参考になるだろう。
ちなみに、OnlyCSViewでは「表示」ボタンと、テーブルの視認性を上げる奇数行ハイライトで明示的に使っている。それぞれ、class=”btn btn-primary”という指定と、class=”table table-striped”という指定をしているだけ。なお、文字コード選択のセレクトメニューの見た目も変化しているが、こちらはclass指定をせず勝手に変更されたもの。こういったおせっかいもあるので、それが気にならない人間がBootstrapに手を出せばよい。

BootstrapのCDNはよ

こういった仕事で使うにはちょっと…というおもちゃは、すぐに影響なく外せるよう、CDNで利用したい。Bootstrapにも勿論CDNがあるので、魔法の呪文を書いておこう。

<!--Bootstrapの本体(ヴァージョンは適宜)-->
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet">
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>

jQueryが必須になる。ちなみに、レスポンシブ対応させるには、もう一つ二つファイルを読み込まないといけない。そちらはCDNが無いので、ダウンロードしてくるしかないけど。
ちなみに、このCDNを提供しているNetDNAという会社は、本来はCDNを商売にしている会社なので、急にサービスの停止などされる可能性はある。自己責任で。

OnlyCSViewの機能増えてないけど?

本当は見た目の更新だけでなく、ファイルのドラッグ&ドロップに対応させようとして、仕組みは書いていたのだけど。ただ、一般的なファイルダイアログを使ったアップロードと、ドラッグ&ドロップによるアップロードで同じGUIを使うというところに無理があったため、どうしようかと思っている。賑やかしで置いているだけで、利用者もいないだろうし別の開発を優先する予定。


var_dumpよりログ作成に便利なvar_export

PHPで変数をダンプしたいとき

PHPでプログラムを書いていて、処理の一時点での変数の値を参照したいとき。通常であれば、var_dumpやprint_rなどの関数を使います。

$ar = array(
array(1,"愛媛県",array("県庁所在地" => "松山","名物" => "みかん")),
array(2,"香川県",array("県庁所在地" => "高松","名物" => "うどん"))
);
 
//var_dumpの場合
var_dump($ar);
//標準出力への出力結果
array(2) { [0]=> array(3) { [0]=> int(1) [1]=> string(9) "愛媛県" [2]=> array(2) { ["県庁所在地"]=> string(6) "松山" ["名物"]=> string(9) "みかん" } } [1]=> array(3) { [0]=> int(2) [1]=> string(9) "香川県" [2]=> array(2) { ["県庁所在地"]=> string(6) "高松" ["名物"]=> string(9) "うどん" } } }
 
//print_rの場合
print_r($ar);
//標準出力への出力結果
Array ( [0] => Array ( [0] => 1 [1] => 愛媛県 [2] => Array ( [県庁所在地] => 松山 [名物] => みかん ) ) [1] => Array ( [0] => 2 [1] => 香川県 [2] => Array ( [県庁所在地] => 高松 [名物] => うどん ) ) )

var_dumpとprint_rの違いについては、print_rの方が変数を見やすく出力してくれるという説明がされています。変数型のような余計なものがついていませんが、値の確認程度ならprint_rでも間に合いますね。

変数のダンプ結果を文字列として扱いたいとき

通常のダンプだけでなく、たとえばある時点での変数の値をデータベースに格納したい場合、特定のメールアドレスに送信してログを残したい場合、などは、一度標準出力をob_startとob_get_contentsなどを使ってバッファリングした上でvar_dumpなど行う必要があるように思えます。
それらを一緒くたに、変数を展開して即文字列型にしてしまうのがvar_export関数です。

var_export関数は引数を二つとり、第一引数が文字列に展開する変数、第二引数がブーリアン型で、falseならばそのまま標準出力に出力、trueならば出力はせず、返り値として文字列を返します(デフォルトはfalse)。

$ar = array(
array(1,"愛媛県",array("県庁所在地" => "松山","名物" => "みかん")),
array(2,"香川県",array("県庁所在地" => "高松","名物" => "うどん"))
);
 
//var_export
var_export($ar);
//標準出力への出力結果
array ( 0 => array ( 0 => 1, 1 => '愛媛県', 2 => array ( '県庁所在地' => '松山', '名物' => 'みかん', ), ), 1 => array ( 0 => 2, 1 => '香川県', 2 => array ( '県庁所在地' => '高松', '名物' => 'うどん', ), ), )
 
//var_exportの第二引数にtrueを指定して変数に格納
$return = var_export($ar,true);

var_exportの出力は、print_rと同じように変数型については省略のようですね。また、配列の最後には、次に続く要素が無くてもカンマをつける癖があるみたいです。細部に注意は必要ですが、これでログの作成が容易になります。


PHP5.5のリリースに合わせて、php.netをリニューアルしたそうな

いつも大変お世話になっております、php.net。久しぶりにじっくりと舐め回すように眺めたら、ページの頭の部分に”Step into the future! Click here to switch to beta php.net site”という文字が書かれている。どうせスパムリンクだろうと思って迷わずクリックしたら、php.netのリニューアルヴァージョンが出てきた。

PHPのヴァージョンも5.5でキリが良いし、php.netもいっちょリニューアルしておくかということらしく、今後はリニューアル後も一向にあか抜けない見た目の、新ヴァージョンに切り替えるらしい。なにこれ、jQuery(おまけにjQuery UIまで!)とか使ってしまって、PHPerとしては軟派になったphp.netを許せない!静的サイトで作り直せ!

ということを愚痴っても仕方が無いので、PHP5.5まわりについて言及しておこう。PHP5.5がリリースとなった事で、決まり通り2ヴァージョン前の5.3のサポートが打ち切られるということになるはずだけど、結局1年間は延長サポートになるらしい。

大抵のレンタルサーバって、PHPのヴァージョン5.2.8か5.3.6かを選ばせている段階だろうから、サポートが少し伸びた事は朗報だろうか。5.4が嫌悪されたということなのかねぇ。

PHP5.5では、cURLがHTTP Pipeliningに対応した。つまりこれまで作ったプログラムを通信部分が高速なものに書き直せるということで、非常に興味があるのだけれど、これまで作ったプログラムはまだ5.4の壁を越えられていないので…

まず5.4の変更点を慌てて読み返す作業にとりかからねば。


WordPress.comでTwenty Thirteenを試す

WordPressのサイトを新しく始めようと思った時、まずレンタルサーバを借りて、WordPressを手順通りインストールして…というような手続きが必ずしも必要というわけではない。というのは、WordPress.comという公式が提供するASPが存在するからだ。WordPress.com(日本語版)

このサービスに登録すると、×××.wordpress.comというアドレスが貰え、不要なインストールをせずにWordPressのブログページが作成できる。勿論、広告が多少入り、また完全版より機能が劣っているという制限はあるのだが、少しの気まぐれで思いついたサイトを実現するには、手軽で丁度良い。WordPress形式なので、本格的にサイトを始動しようと思った時は、データベースのエクスポートをして移行すれば良い。

私はTwenty Thirteenを見た。

このWordPress.comだが、デフォルトのテーマ選択肢の中に、Twenty Thirteenが入っている。最近Twenty Twelveが正式版になったばかりだという印象もあったのだが、何とも気の早いことで、ベータヴァージョンというわけでもなく使えてしまうのである。各所で話題になっているようだが、今回のデフォルトテーマの見た目は非常にポップである。

Twenty Thirteen見た目

Twenty Thirteen見た目

これまでのものと比べ、アクの強さもかなりある。きっともう増やす機能がなかったので、メジャーリリースのインパクトを損じないようにデザインを大きくいじったのだろう。

おそらく、最大の目玉機能となるのは、WEBフォントの全面採用。アイコン類もフォントにすることで、真にスケーラブルな、レスポンシブデザインに近づけたということなのだろう。まあ、正直時期尚早だと思っているのだが、これまでも、WordPressが先進技術を積極的に採用してきてくれたおかげで、それらの技術がWEB標準に育っていったという経緯を見ているので(HTML5やレスポンシブデザインね)、諸手を上げて歓迎しておこう。

で、WordPress.comは実用に足るのかということだけど、プラグインが使えない。この時点で、選択肢から外れてしまう。ただ、WordPressの事が何も分からないという人に手っ取り早くブログを作らせるには、インストールもいらないWordPress.comを勧めておけば良いということだろう。