- ベストアンサー
リファラを取得するためのCGI
アクセスログを取るためのcgiをPerlで作っています。 例えば、 hogehoge.html というページのアクセスログを取るためにlog.cgiというスクリプトを用意します。 hogehoge.htmlからは、IMGタグを使用して、<IMG src="log.cgi">のようにcgiを呼び出しています。 log.cgiからは、ダミーのgifファイルを返します。 ここで、log.cgiでは訪問者のリファラを取得して記録するようにしていますが、この仕組みだとhogehoge.htmlがリファラとして記録されてしまいます。(hogehoge.htmlが呼び出したのだから、当然ですね) hogehoge.htmlへアクセスしたブラウザが持ってたリファラを取得するには、どのようにすればよいでしょうか? 今回はIMGタグでcgiを呼び出していますが、特に手段は選びません。 ちなみに、使用しているサーバーではSSIは使えません。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
cgiでの誤動作を防ぐために全角文字をurlに入れたのでは逆行ですよ(cgi実行以前のところで誤動作する可能性がある)。 「&」は大文字ではなく全角2バイト文字です。 私が参考にしたアクセス解析(http://www.futomi.com/)では、queryから取得して&で分解したデータをもう一度繋ぎ直してますね。 他のデータは必要なくてqueryにはreferrer文字列しか入れないことにすれば、以下のようにシンプルになりますが。(参考 http://www.kent-web.com/) -- javascript 記述 -- document.write("<img src='log.cgi?"+document.referrer+"'>"); -- perl 記述 -- $ref = $ENV{'QUERY_STRING'};
その他の回答 (5)
- taseki
- ベストアンサー率66% (155/233)
「&」を全角の「&」にしてしまってはいけない、というのはANo.5の方のおっしゃるとおりですが(そもそも許されるURL形式ではない)、escapeの使用も注意が必要です。 その前に、まずそもそも、「&」だけにこだわっておられるようですが、URLエンコーディングのルールとして、特殊文字はすべて「%XX」という形式にしなければいけません。2バイト文字はもちろん、「&=%+」やスペース文字もです。 正しくエンコーディングされていないと、受け取る側のスクリプトで正しく解釈できないだけでなく、まずURLとして許されないのでスクリプト以前にちゃんと送られるかどうかも保証されません。 そこでescapeを使ってエンコードするわけですが、ANo.4の方がおっしゃっているように、最近のブラウザは一度UNICODEに変換してからURLエンコードするものがあるので、期待通りのデータにならない場合があります。 受け取る側のスクリプトでUNICODEに対応しておくのが最善策ですが、Jcodeモジュールなどが使えない場合は面倒になります(新しいperlなら標準)。 ブラウザを判定して、たとえばIE5以上だったら encodeURI や encodeURIComponent が使える、などという手もあります。 とは言え、そもそもやろうとしているのがアクセス解析なのですから、エンコードデータから検索キーワードを調べたりもすると思われ、各文字コードに対応しているのかもしれませんね。
お礼
>ブラウザを判定して、たとえばIE5以上だったら encodeURI や encodeURIComponent が使える、などという手もあります。 これだと、将来新しいブラウザが出た場合に、JavaScriptを修正する必要がありますね。今回は、プライベートなサイトなので、そこまで保守に労力をかけたくないので、#5さんの方法にしようと思います。 すみません。ありがとうございました。
- steel_gray
- ベストアンサー率66% (1052/1578)
#3補足。 とりあえず&記号による誤作動を防止するためにescapeを紹介しましたが 実行結果(エンコード方式)が異なるブラウザもあるので 検索エンジンから来た場合のキーワード(日本語)を調べるような場合には注意が必要です。→参考URL
お礼
重ね重ね、ありがとうございます。 結構、難しいものですね。refereが検索エンジンの検索結果URLだった場合、そのURL自体がすでにエンコードされているので、それをさらにエンコードするのはどうか、ということに気づきました。 で、encodeを使用するもともとの発想は、#4==#3さんが言われるようにrefereに&が入っていた場合の誤動作を防ぐということなので、refereに&が入ってきた場合に大文字の&に変換してからlog.cgiに引き渡すという方法で逃げようと思います。で、log.cgiでは、大文字&を小文字&に戻すと。 慣れないJavaScriptで、こんな感じで作ってみました。 <SCRIPT language="JavaScript"> <!-- REF = document.referrer; REF = REF.split("&"); REF = REF.join("&"); document.write("<img src='log.cgi?ref="+REF+"'>"); // --> </SCRIPT> <NOSCRIPT> <IMG src="./log.cgi"> </NOSCRIPT>
- steel_gray
- ベストアンサー率66% (1052/1578)
#1さんの方法を使う場合、?~&~が付いているURLだった場合を考慮して document.write("<img src='log.cgi?ref="+escape(document.referrer)+"'>"); としておいたほうがいいかも。 refererが hoge.cgi?aaa=bbb&ccc=ddd だった場合・・ escapeなし <img src="log.cgi?ref=hoge.cgi?aaa=bbb&ccc=ddd"> escapeあり <img src="log.cgi?ref=hoge.cgi%3Faaa%3Dbbb%26ccc%3Dddd"> となります。(urlエスケープされる)
お礼
なるほど、"&"が複数になった場合、2つ目の"&"以降が無くなってしまうのですね。 検索エンジンからの来訪の場合に、どんなキーワードの検索結果だったのかが分からなくなるということですね。 勉強になります。ありがとうございます。
- taseki
- ベストアンサー率66% (155/233)
> これだとJavaScriptを使用しない設定の人からのアクセスには対応できません ANo.1の方の方法は、とても一般的な方法だと思いますよ。 つまり、一般的に、JavaScriptオフのためロギングされないのは、誤差の範疇と捉えられます。 少しでも誤差を少なくしたいなら、やはりSSIが理想ですが、仮にSSIが使えたとしても誤差はゼロにはなりません。 これはもうインターネットの仕組み上どうしようもないと言えるでしょう。 どうしても、SSIもJavaScriptも使わずに誤差を少なくしたいなら、たとえばですが、「hogehoge.html」というファイル名のスクリプト(中身はHTMLではなく実はスクリプト。実行ファイルとしての設定をしておく)を作り、アクセスされたらリファラを付けて log.cgi をコールしてから、本来の「hogehoge.html」のHTMLデータを(ファイルから読み取るなどして)そのまま出力、という方法も可能だと思います。 あるいはhtaccess の Action を使って、 Action text/html /~log.cgi としておき、HTMLへのアクセスがあればlog.cgiが呼び出されるように設定しておく、など。
お礼
回答ありがとうございます。 「誤差の範疇」と言われて、ちょっと安心しました。 携帯電話やPDAなどからのアクセスを記録できないなと思い心配していましたが、<NOSCRIPT>でJavaScript非対応からのアクセスもリファラ無しで記録できるので、よしとします。 今回は、プライベートなサイトなので、個人契約しているプロバイダのサーバーを使用します。そのプロバイダでは、.htaccessが使用できないので、ちょっと自由に設定変更はできそうにありません。 .htaccessのActionってのは知らなかったです。勉強になります。ありがとうございました。
- 2NN
- ベストアンサー率40% (143/353)
<SCRIPT language="JavaScript"> <!-- document.write("<img src='log.cgi?ref="+document.referrer+"'>"); // --> </SCRIPT> これで取得できると思います。
お礼
回答ありがとうございます。 リファラを取得することができましたが、これだとJavaScriptを使用しない設定の人からのアクセスには対応できません。他によい方法がありましたらお願いします。 余談ですが、JavaScriptの場合は、綴りがrefererではなくreferrerなんですね。
お礼
失礼しました。encodeする意味を完全に見失ってました。URLにDBCSが混ざったら駄目ですよね。 今までGET/POSTデータの読み取りはライブラリに任せていたのですが、自分で&でsplitすればよいのですね。ありがとうございます。