17時20分47秒 [Web関連]
メールアドレスをテキスト形式でウェブ上に掲載しておきつつも、メールアドレスを自動収集プログラムに収集されてしまうのをできるだけ防ごうとする方法の1つに、「メールアドレスを構成する文字列をASCIIコードの数値に変換してJavaScriptで文字列に戻して表示」する方法があります。
……文章で説明すると分かりにくいですが。(^_^;)
例えば、「test@example.com」というメールアドレスを掲載したいとき、このメールアドレスを構成する文字を1つずつASCIIコードに変換して、
116, 101, 115, 116, 64, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109
という数字の列にします。
ASCIIコードでは、「t」は116、「e」は101、「s」は115……なので上記の数字列になります。
この数字列をJavaScriptソースに記述しておき、スクリプトを使って「ASCIIコードを文字に戻す」ことで、ソース中には数字しか記述していないのに、ウェブページ上には(人間が目で見てわかる)メールアドレスが表示できます。
メールアドレスの存在を(自動収集プログラムからは)分かりにくくする方法
この方法が「メールアドレスの暗号化」と紹介されることもありますが、暗号と呼べるほどの処理はしていません。文字とASCIIコードは1対1で対応していますから、デコードは簡単です。しかし、メールアドレスをそのままソースに記述するわけではないので、単にファイルを読んでメールアドレスの存在を検索するだけの自動収集プログラムからは、メールアドレスを守れる可能性が高まります。(ただし、ブラウザと同様にJavaScriptを実行し、その結果の中からメールアドレスを探すような賢いプログラムにはあっさりバレます。)
そんな、「メールアドレスを構成する文字列をASCIIコードの数値に変換してJavaScriptで文字列に戻して表示」するために必要なJavaScriptソースを生成するツールを公開しました。
ツールといっても、ブラウザ上で動作します。
■メールアドレスを数字列にしてJavaScriptで記述するソース生成ツール
この方法だと、HTMLソースしか読まない自動収集ロボットはもちろん、JavaScriptソースを単純に読むことしかしない自動収集ロボットからも収集を防げます。
単純なASCIIコード値の羅列にしない工夫
ただ、単純にASCIIコードにしただけだと、「ASCIIコードの羅列だ」と当たりを付けられたときにバレやすそうな気がします。特に、メールアドレスの特徴的な文字である「@」記号は「64」なので、「カンマ区切りの数字列」の中程に「64」が登場する場合には、「もしかしてメールアドレスかも?」と自動で推測することは不可能ではない気がします。
というわけで、今回作ったツールでは、適当に数値を増減させる「数式列」で表せるようにしてあります。
例えば、先ほどの数字列は、適当な加減算を含んだ、
134-18, 99+2, 139-24, 115+1, 93-29, 79+22, 133-13, 75+22, 125-16, 81+31, 137-29, 95+6, 54-8, 68+31, 138-27, 108+1
……のような列になります。
「t」は116ですが「134-18」と記述、「e」は101ですが「99+2」と記述、「s」は115ですが「139-24」と記述するようになっています。これだと、先ほどよりも分かりにくくなっているでしょう。
増減する値はランダムに決定しているので、同じメールアドレスでも変換を実行する度に計算式列は異なります。
何度も言いますが、ブラウザと同様にJavaScriptを「実行」して、その結果の文字列からメールアドレスを抽出しようとするプログラムによる自動収集は防げません。(いずれはそうなりそうな気もしますが)
それも防ぎたい場合は、画像化するとか、もっと他の手段が必要です。
このツールで生成されるJavaScriptソースの例
このツールで生成されるJavaScriptソースは、以下のようなものです。
function secretaddress() {
var ma = String.fromCharCode(134-18, 99+2, 139-24, 115+1, 93-29, 79+22, 133-13, 75+22, 125-16, 81+31, 137-29, 95+6, 54-8, 68+31, 138-27, 108+1);
var mt = String.fromCharCode(126-17, 66+31, 110-5, 71+37, 153-37, 91+20, 92-34);
document.write('<a href="'+ mt + ma + '">' + ma + '</a>');
}
変数maには、メールアドレスをASCIIコードにした値(を計算式でちょっとだけ複雑にしたもの)が入ります。
変数mtには、「mailto:」の文字列が同様の方法で入ります。ついでなので、こちらもASCIIコードに変換しています。(^_^;)
あとは、HTML内のメールアドレスを掲載したい箇所で、secretaddress関数を実行すれば、メールアドレスリンクが表示されます。
この変換ツール(CGI)を作っているPerlプログラムは
ちなみに、このJavaScriptソースの出力(というか、ASCIIコードに変換する処理)にはCGI(Perl)を使っていて、以下のようなソースを実行しているだけです。
my @asciiNums = unpack("C*", $targetMailString);
変数$targetMailString内の文字列を1つ1つASCIIコードの10進数に変換するのは、unpackを使うだけです。ループなどは不要で簡単ですね。変換結果は、配列@asciiNumsに入ります。
また、数値の配列をカンマ区切りにするには、以下のようにjoinを使うだけなので、やはりループは不要です。便利だな……。(^_^;)
my $outputs = join("," , @asciiNums);
ランダムな数字を使って計算式の形を作るところだけではループを使っていますが。
やっていることは、0~32のランダムな整数をrandで取得して、足したり引いたりするだけです。
my $cloop = 0;
foreach my $onenum ( @asciiNums ) {
# 増減分を乱数で決定
my $pmrand = int(rand(32));
# 増減式を含んだ値に変更(+-は交互)
if( $cloop % 2 == 0 ) {
$asciiNums[$cloop] = ($onenum + $pmrand) . "-$pmrand";
}
else {
$asciiNums[$cloop] = ($onenum - $pmrand) . "+$pmrand";
}
# ループを進める
$cloop++;
}
増減パターンもランダムにしようかと思ったんですが、まあ面倒だったので交互にしました。(^_^;) そこを拘っても意味はないと思ったので。(もっとも、それを言ったら、そもそも加算と減算を混ぜる必要性もありませんけども。^^;;;)
得るランダムな値の範囲を0~32にしたのは、ASCIIコードの中で画面に表示可能な文字の最初(空白文字ですが)が32だからです。引き算したときに値がマイナスになっちゃうと、JavaScriptソースの中でマイナス記号が2つ連続する可能性があってうまく動かないよな……と思ったからなんですが、よく考えたらそんな可能性はない気もしてきました。(^_^;)
まあ何にせよ、別に33種類も増減パターンがあれば充分でしょう。(^_^;)
というわけで、クリック可能なメールアドレスリンクを掲載したいものの、自動収集はできるだけ防いでおきたい……という場合(特に企業サイトなどで、顧客からの問い合わせを容易にしておきたい場合とか)の対策の1つとして、ご活用ください。