Perl/CGI研究室 'PERL-LABO'

Perl/CGI研究室 'PERL-LABO' TOPへ
戻る(History.Back)

複数のCGIプログラムを1つに

研究内容

アクセスカウンター、ページビューカウンター、リファラーカウンター、 検索キーワードカウンターの4つのカウンターを1つのCGIプログラムにまとめる研究です。

詳細

1つにまとめるメリット

ここまで複数のCGIプログラムを作成してきました。 このサイトでは、現在4つのCGIプログラムを各ページから呼び出しています。 1つのページが開かれると、実は、 アクセスカウンター、ページビューカウンター、リファラーカウンター、 検索キーワードカウンターの4つのCGIプログラムが起動されるんです。 そして、それぞれのCGIプログラムはそれぞれの役割を果たします。

これ、ちょっとした問題があります。 CGIプログラムの実行はサーバーに負荷をかけますが、 特に、CGIプログラムを起動するという処理はサーバーへの負荷が大きいです。 詳細な研究はしていませんが、四則演算を数十万回するよりも 1つのCGIプログラムを起動する処理の方が大きな負荷がかかるようです。

よって、ページが開かれるたびに呼び出されるという共通の特徴をもっている これらバラバラになっているCGIプログラムを1つにまとめることができれば、 CGIプログラムの起動が1回だけですみ、サーバーへの負荷を大きく軽減することが できます。それに、CGIプログラムの設置も簡単になりますよね。 できることなら、これらCGIプログラムは1つにまとめたいのです。

このために準備をしてきました

複数のCGIプログラムを1つにまとめるという一般的な方法があるわけではありませんが、 このサイトで作成してきたこれらのCGIプログラムに関しては、 それぞれを自由に組み合わせて1つのCGIプログラムにまとめることができるような、 下準備をしてあります。それは、プログラム本体をライブラリの中に入れてしまって、 CGIプログラム本体からは1つの関数を呼び出すだけっていう状態にしてあることです。

この状態なら、複数のCGIプログラムを1つにまとめることも可能なはず! 関数1つでCGIプログラム1個分の仕事をすることができるのですから、 関数を4つ呼び出せば4つのCGIプログラム分の仕事ができるはずですよね。 ということで、今回の研究で今までの下準備が実るか? トライしてみましょう!

結果

まとめる方法

それぞれのカウンターは1つのCGIプログラムにまとめることを念頭に作成してありますから、 難しくありません。

カウントを行うためのCGIプログラム呼び出し時には、 CGIプログラムはそれぞれのカウンターを1つずつ呼び出します。

カウンターの履歴表示画面を表示する場合は、指定したカウンターのみを呼び出します。 それぞれのカウンターは ?v=graph とすると履歴画面が表示されるんですが、加えて、 URLに &f=〜 というのを付けて、それで表示するカウント履歴を指定するようにしました。 f は、function の略のつもりです。 次のような感じです。

〜.cgi?v=graph&f=ac	アクセスカウンターの履歴画面を表示します
〜.cgi?v=graph&f=pv	ページビューカウンターの履歴画面を表示します
〜.cgi?v=graph&f=rc	リファラーカウンターの履歴画面を表示します
〜.cgi?v=graph&f=sw	検索ワードカウンターの履歴画面を表示します

f=〜 を指定せずに次のようにCGIプログラムを呼び出した場合は、 アクセスカウンターの履歴画面が表示されるようにしました。

〜.cgi?v=graph		アクセスカウンターの履歴画面を表示します

それぞれの履歴画面では、ページ上部に メニューが付くようしていますので、 それぞれの履歴画面を行ったり来たりするのは簡単です。 メニューを表示したくない場合は menu=off というのを付けて呼び出します。

与えるデータで処理を分けるっていうのは便利なものですね! 1つのCGIプログラムにいろんなことをさせることができます。 あと、それぞれの履歴画面はパスワードを設定して他人にみられないようにする機能がありましたので、 今回も、メニューをパスワードで保護する機能を付けました。

もともと1つのCGIプログラムにまとめることを念頭に作成してあっただけあって、 それほど苦労なく作成することができました!

作成したCGIプログラム

plabanalyzer.cgi
#!/usr/bin/perl

# Plab Analyzer v1.00

# (c) PERL-LABO
# http://www.perl-labo.org/

use CGI::Carp qw(fatalsToBrowser);

require 'setting.cgi';

require 'plabcounter.pl';
require 'pvcounter.pl';
require 'refcounter.pl';
require 'searchword.pl';

require 'getformdata.pl';
require 'stdplab.pl';

%form = plab::getformdata();

if ($form{'v'} ne "")
{
	# f が指定されていなければアクセス履歴モードにする
	if (! exists($form{'f'})) { $form{'f'} = "ac"; }

	# メニューがパスワードで保護されていないか、または
	# メニューパスワードが指定されていればページ先頭のメニューを作る
	if ($form{'menu'} ne "off") {
		if ($pa_pswd eq "" || $form{'menupswd'} eq $pa_pswd) {
			$menu = makemenu();
			$html_head .= $menu . "<br><hr size=1><br>\n";
			$homeurl = "";
		}
	}

	# ページ末尾のソフト名を書き換える
	$html_appname = "Plab Analyzer v1.00";

	# 各カウンターのグラフ表示を行う
	if    ($form{'f'} eq "pv") { if (plab::exec_pvcounter())   { exit; } }
	elsif ($form{'f'} eq "rc") { if (plab::exec_refcounter())  { exit; } }
	elsif ($form{'f'} eq "sw") { if (plab::exec_searchword())  { exit; } }
	elsif ($form{'f'} eq "ac") { if (plab::exec_plabcounter()) { exit; } }

	# メニューを表示して終了
	print "Content-type: text/html\n\n";
	plab::printhtmlheader();
	plab::printhtmlfooter();
}
else
{
	# 各カウンターのカウントモード
	if (plab::exec_pvcounter())   { exit; }
	if (plab::exec_refcounter())  { exit; }
	if (plab::exec_searchword())  { exit; }
	if (plab::exec_plabcounter()) { exit; }

	# 透明gifを出力して終了
	plab::toumeigif();
	exit;
}

# メニューを作る
# デフォルトのfも返す
# 戻値 配列で (メニューHTML, デフォルトのf
sub makemenu
{
	local ($menu, $ls, $le, $p, $mpswd);

	# 各詳細ページを閲覧可能かどうかを調べ、
	# 詳細ページへのリンクを作成する

	# メニューがパスワード保護されていない場合、
	#  パスワードで保護されている詳細ページにはリンクしない

	# メニューがパスワード保護されている場合、
	#  パスワードで保護されている詳細ページにもリンクする

	if ($pa_pswd ne "") { $mpswd = "&menupswd=$pa_pswd"; }

	# アクセスカウンター
	if ($pa_pswd ne "" || $ac_pswd eq "") {
		$ls = ""; $le = ""; $p = "";
		if ($form{'f'} ne "ac") {
			if ($ac_pswd ne "") { $p  = "&pswd=$ac_pswd"; }
			$ls = "<a href=?v=graph&f=ac$p$mpswd>";
			$le = "</a>";
		}
		$menu .= "[$lsアクセス$le] \n";
	}

	# ページビューカウンター
	if ($pa_pswd ne "" || $pv_pswd eq "") {
		$ls = ""; $le = ""; $p = "";
		if ($form{'f'} ne "pv") {
			if ($ac_pswd ne "") { $p = "&pswd=$ac_pswd"; }
			$ls = "<a href=?v=graph&f=pv$p$mpswd>";
			$le = "</a>";
		}
		$menu .= "[$lsページビュー$le] \n";
	}

	# リファラーカウンター
	if ($pa_pswd ne "" || $rc_pswd eq "") {
		$ls = ""; $le = ""; $p = "";
		if ($form{'f'} ne "rc") {
			if ($rc_pswd ne "") { $p = "&pswd=$rc_pswd"; }
			$ls = "<a href=?v=graph&f=rc$p$mpswd>";
			$le = "</a>";
		}
		$menu .= "[$lsリファラー$le] \n";
	}

	# 検索ワードカウンター
	if ($pa_pswd ne "" || $sw_pswd eq "") {
		$ls = ""; $le = ""; $p = "";
		if ($form{'f'} ne "sw") {
			if ($sw_pswd ne "") { $p = "&pswd=$sw_pswd"; }
			$ls = "<a href=?v=graph&f=sw$p$mpswd>";
			$le = "</a>";
		}
		$menu .= "[$ls検索ワード$le] \n";
	}

	if ($homeurl ne "") {
		$menu .= " [<a href=$homeurl target=_top>トップページ</a>] \n";
	}

	return $menu;
}

実行結果

当サイトの各ページから作成したCGIプログラムを呼び出すようにしました。 次のリンクをクリックしてみてください。 いずれも今回作成したCGIプログラムを起動します。 呼び出し時に与えるデータが違うので、表示される画面が変わります。

アクセスカウンター履歴画面(メニュー無し)
ページビューカウンター履歴画面(メニュー無し)
リファラーカウンター履歴画面(メニュー無し)
検索ワードカウンター履歴画面(メニュー無し)

アクセスカウンター履歴画面(メニュー有り)

解説

plabanalyzer.cgi

ちょっとごちゃごちゃしてしまいましたが、 ほとんどがメニューのHTMLを出力するためのものです。 実際にそれぞれのカウンターを呼び出しているのは次の部分。 (これ以外は全て、メニューのHTML出力のための処理です。)

elsif ($form{'v'} ne "")
{
	# 各カウンターのグラフモード
	if ($form{'f'} eq "pv") { if (plab::exec_pvcounter())   { exit; } }
	if ($form{'f'} eq "rc") { if (plab::exec_refcounter())  { exit; } }
	if ($form{'f'} eq "sw") { if (plab::exec_searchword())  { exit; } }
	if ($form{'f'} eq "ac") { if (plab::exec_plabcounter()) { exit; } }
}
else
{
	# 各カウンターのカウントモード
	if (plab::exec_pvcounter())   { exit; }
	if (plab::exec_refcounter())  { exit; }
	if (plab::exec_searchword())  { exit; }
	if (plab::exec_plabcounter()) { exit; }
}

このように、各カウンターをずらずら呼び出すだけでOKです。 各カウンターは、自らなにか画面表示を行った場合は 1 を、 画面表示を行わなかった場合は 0 を返すようにしています。 途中で 1 が返ってくると、if 文の { exit; } が実行されてCGIプログラムが 終了します。これは、カウンターの中でエラーが発生した場合に、 エラーメッセージが画面に表示されるので、そこで実行を停止するためにこうしています。

さらに他のカウンターを追加することもできます

今回は4つのカウンターを1つにまとめました。 まだ研究していないのですが、今後、もう1つ、アクセス解析を行うCGIプログラムの作成に トライしようと考えているんですが、そのCGIプログラムが完成したときに、 今回作成したCGIプログラムに加えることも難しくありません。 4つのカウンターを呼び出しているところを5つにすればいいんですね。

1つ1つのカウンターはそれほど高機能というわけではありませんが、 こうして1つにまとめると、1個のCGIプログラムを呼び出すだけでいろんな情報が自動的に 蓄積されるということで、なかなか豪華なCGIプログラムになったような気がしますね (^^

補足:改良報告

リンククリックカウンターの追加

さらに、リンククリックカウンターも追加しました。 リンククリックをカウントするのは他のCGIプログラムで行いますが、 グラフの表示を他のカウンターと同じ画面でできるようにしました。 また1つ、かしこいCGIプログラムに改良することができました(^^

Perl/CGI研究室 'PERL-LABO' TOPへ
戻る(History.Back)

Copyright (c) 'PERL-LABO' All Rights Reserved.  リンクフリーです。