アクセスログ

 今回はアクセスログです。前回前々回の関数を使用するので、そちらも見ておいてください。

カウンターとログの違い。
 今回作製するのはアクセスログです。アクセスログとは「どのページがどれだけ読まれているのか」をチェックするものです。すべてのホームページのヒット数をチェックして、どのページがどれだけ人気があるのか、そういったことをチェックすることが目的です。

 本来、インターネットサーバーはこのアクセスログをちゃんと取っていて、それをデータベースに保存しています(ちゃんとしたプロバイダなら、CD−Rなどに保存して半永久的にバックアップします)。ですから、このデータベースを検索すればアクセスログは作製できるというわけです。
 が、もちろんこれはプロバイダが管理する物なので、我々ホームページディレクターには見せてもらえません。そこで、自分でアクセスログを作製してしまおうというわけです。

 実際、このアクセスログはカウンターよりも重要です。ホームページを作製しているとどうしても情報を「発信する」ことにのみ意識が向きがちです。でも実際には、ページごとにヒット数は大きく違い、分野ごとの人気の差も大きくあります。
 手前味噌の話ですが、KAB−studioのページではCodianがもっとも高い人気を誇り、KAB−studioに訪れた人の70−90%の人はCodianのページにも行きます。ところが、そのCodianの各コンテンツは、どのページも2桁を超えないのです!! メニューのページに80人ほど来ても、その次のページへは10人超えるか超えないかくらいのお客さんしか来ないのです!
 こういったデータは表紙のアクセスカウンターだけでは絶対に分からないものです。トップページにそれなりのヒット数があれば、誰だって「どのページも読まれてる」と思ってしまいます。でも実際には違うのです。もしかしたら、リンクのページだけ見て他のページへの通り道にしかなっていないかもしれないのです。
 そういった「思い込み」を排除し、正確なデータを取るためのCGIが、アクセスログというわけです。

CGIの仕様
 そのアクセスログの方針ですが、「画像を表示するCGI」をベースに「アクセスカウンター」の別バージョンといった感じのものにします。
 カウンターとの違いは、まず数字を表示しない、これは当然ですね。また、見やすさを考えてひとつのファイルにすべてのデータを保存することにします。カウンターよりも簡単そうですが、それなりの難しさがあります(なかったら分けて説明したりしません(汗))。
 ホームページに貼り付けるときには、次のような形にします。


<IMG SRC="AccessLog.cgi?http://www.kab-studio.biz/" WIDTH="1" HEIGHT="1">

	

 このように、第1引数にホームページのURLを入れます。そうすると、このページのヒット数がカウントされるというわけです。
 ちなみに実際には、ホームページのメンテナンスを考えて、JAVAスクリプトを使ってURLを渡します。その解説は次回にでも行います。また、ホームページ名に+が入っていると「引数の分割」と判断されてしまうため、そのための処理も必要です。
 また、データは次のようにファイルに書き込むことにします。


http://www.kab-studio.biz/ 000001
http://www.kab-studio.biz/start.html 000060
http://www.kab-studio.biz/nikki2/nikki.html 000001

	

 このように「URL カウント数」という行が並ぶ形になります。カウント数が6桁の理由はあとで説明します。
 また、6桁なのからも分かるように、このログは毎日保存し、その都度空のログと置き換えます。つまり毎日データを取っていくわけですね。もちろん桁数を増やせばずーっとログを取ることもできますが、はっきり言って無意味です。ある程度時間を短く区切って、いつ人気があるのかとか、日毎に人気が下がっているのかとかをチェックするのがいいと思います。

下準備
 「バックグラウンドで動作するCGI」なので、CGIの置いてあるディレクトリに1ドット透明GIFを置いておいてください。ファイル名はTPDot.gifにしておいてください。実行時にこのイメージが表示されるようにします。ホームページのバナーにして、すべてのページに表示させるなんていうのもいいでしょう。
 カウンターデータを保存するファイルも置いておいてください。ファイル名はAccessLog.txt。中身は空でいいでしょう。書き込みを行うため、パーミッションは「グループ・他人でも書き込み可能」にしておいてください。chmod go+w AccessLog.txtとかすればOKです。カウンターと違い、データはこのファイルにすべて書き込むので、これひとつだけあれば十分です。
 準備はこれだけ。ではプログラムを。

プログラムについて
 実際のプログラムはこちらです。
 このリンクは新しいブラウザウィンドウを開きます
 このプログラムは著作権フリーとします。
 このプログラムを使用することによるいかなる損害にも関知しません
 動作確認はリムネットだけです。他のプロバイダでは確認してません。
 このプログラムを使用するときには拡張子をcにしてください

画像の出力
 まずいきなり、画像を出力します。今回のCGIは画像を出力することに意味はないからです。ここでは1ドットの透明GIFを出力しています。

引数の処理
 渡された引数ですが、実はこのままでは使えません。渡された文字列にはエスケープシーケンスが入っている可能性があります。例えば文字列の中に~とか|が入っていた場合には、\~とか\|に置き換えられています。そのため、このエスケープシーケンスを削除する必要があります。
 そのための関数がDelYen()です。一文字ずつチェックして渡すというちょっとベタな方法を取っています。でも、特に問題はないでしょう。

URLのサーチ
 URLの処理が終わったら、IncCount()に移ります。この関数はアクセスカウンターの同名の関数と似たような実装をしています。データの入ったファイルを開いてロックを掛けるところまでと、ロックを外した後はほとんど同じです。
(注:なぜかlockf()バージョンだとプログラムがうまく働きません!! fseek()がうまく動かないようです。この問題についての情報を知っている、もしくはプログラムバグが見つかったという方はぜひお知らせください!!

 ロックした後は、まずUrlSearch()で同じURLがあるかチェックします。この関数はまずfscanf()で単語を取得していきます。「単語」とは「スペースか改行で区切られた文字列」のことです。だから、この場合には「URL・カウント・URL・カウンター……」という順に取得されていきます。
 取得された単語はstrcmp()で一致するかチェックします。URLはUNIXのパスなので、大文字小文字を区別する必要があります
 一致したらftell()現在のファイルポインタの位置を取得します。
 fscanf()は単語ごとに読み、その都度ファイルポインタを進めていきます。例えばhttp://www.kab-studio.biz/ 000001であれば、最初のURLをfscanf()で読み込んだとき、ファイルポインタは間のスペース(/と0の間)に来ています。次に読み込んだら、最後の改行に来ます。
 ftell()はその「ファイルの先頭からのファイルポインタの位置」を取得します。このファイルポインタは、のちほどカウント数の書き込み時に利用します。
 ファイルポインタの位置を取得したら、もう一度fscanf()を使ってカウント数を読み込み、UrlSearch()から返ります。このとき、先ほど取得した「ファイルポインタの位置」を返します。また、第1引数の文字列を使ってカウント数を返します。
 検索に引っかかることなくファイルの最後まで来たときには、0を返してUrlSearch()から返ります。

「桁数固定」のワケ
 IncCount()に戻ってからはデータの書き込みです。UrlSearch()からが返ってきたときには「URLが見つからなかった」ということなので、ファイルの最後にURLとカウントを追加します
 fseek()はファイルポインタを移動する関数です。第2引数は移動する量、第3引数はフラグで、をセットするとファイルの最後に移動します。ここでは第2引数はなので、単にファイルの最後に移動するということになります。
 で、fprintf()で「URL カウント数(改行)」と書き込みます。このとき、最初のカウント数は1になるわけですが、このプログラムでは「000001」という6桁の文字列にしています。前述しているように、このデータは必ず6桁の文字列として扱っています。この説明はもーちょっと待ってください。
 「URLが見つからなかった場合」にはこれでプログラムが終了します。

 「URLが見つかった場合」には、UrlSearch()で返されたカウント数とファイルポインタを用いてカウント数を更新します。
 カウント数の増加はIncTextCount()で行います。ここではカウント数を「文字列」のまま増やしますatoi()を使わない理由は、000001という値だとエラーが発生してが返ってきてしまう、つまりちゃんと変換されないためです。
 カウントの増加は1桁目(文字列で言えば最後の文字)からチェックし、「くりあがり」がありかつ数字が9の時のみにして「くりあがり」をセット、それ以外はその文字に1を加えます(文字コードは0が0x30、1が0x31、2が0x32と並んでいるのでこういうことができるのです)。ちなみに最初の一桁には「くりあがり」をセットしておくことでプログラムを簡略化してます。

 カウントを増やしたら、ファイルに書き込む前にファイルポインタを移動させます。このとき、先ほど取得した「ファイルポインタのファイルの先頭からの位置」が役に立ちます。
 fseek()の第3引数にをセットすると、「ファイルの先頭から」という意味になります。そこで第2引数に先ほどの「ファイルポインタの位置」を渡すことで、「URLとカウント数の間のスペース」にファイルポインタを移動できるわけです。
 移動したら「 カウント数(改行)」と書き込みます。最初のスペースに注意してください。ファイルポインタがスペースにあるので、そのスペースを上書きする必要があるというわけです。上書きしたら、これでプログラムが終了します。

 さて、ここで「000001」の理由を説明しましょう。
 ファイルへの書き込みは、基本的に上書きです。つまり、挿入はできないというわけです。これは非常に大きな問題です。
 「ファイルへの挿入」を実現するのは非常に難しいことです。一時ファイルを作製してコピーしたり、データをすべて読み込んだり、ファイルの中のデータをひとつずつずらすといったことをしなければなりません。そうなると、プログラムの難易度が飛躍的にアップします。
 そこで、上書きでもOKな形にしようということで、桁数を固定にしたというわけです。この規則のために、数値計算を行わず文字列として処理し、ただの「1」も「000001」として書き込んでいたわけです。

 桁数は、START_COUNTでのの数を変えることで簡単に変更できます。例えば#define START_COUNT "001"なら3桁で処理されます。他の部分で手を加える必要はありません(もちろんデータファイルの形式は変わってしまうので、ずーっと同じファイルを使っている場合には問題が出てきますが)。

応用範囲の広いCGI
 このアクセスログ、何もアクセスログにだけ使う必要はありません。このCGIは「渡された文字列をカウントする」ものです。「文字列」はなにもURLである必要はありません。
 特にJAVAスクリプトと組み合わせることで様々なログを取ることができます。これについては次回に解説する予定です。
 また、今回のCGIはイメージのログを取ることができませんが、このCGIに直接イメージを表示させるようにすれば、イメージのログも取ることができます。画像ファイルのダウンロードをメインとしてるホームページはこういったCGIを作ってみてはいかがでしょう。

(C)KAB-studio 1998 ALL RIGHTS RESERVED.