Создание счетчика посещений на Perl.
Автор: неизвестен
Редактор: Кирилл Шагин


Что ж, сегодня мы научимся создавать простейшие счётчики для личных Web-страниц. Так как этот вопрос не раз задавался в этом журнале. Конечно, все ниже описанное ни коим образом не посягает на идеал, хотя бы потому, что это один из первых моих счётчиков, а может потому, что мне пока 16... не знаю, но знаю точно, что это РАБОТАЕТ!

Итак, начнём.

Разберёмся, какие действия должен выполнять наш счётчик:
1. считать общее количество посетителей
2. считать число уникальных посетителей за день

Теперь обозначим, где будут хранится данные. Я думаю, что удобнее всего их хранить в текстовых файлах, причём таковых будет два: в первом будет храниться вся статистика (т.е. и хиты и хосты). А второй текстовый файл нам очень пригодиться для хранения базы IP. Когда посетитель будет заходить на нашу страничку впервые, то его IP занесётся в базу (чтобы его впредь больше не считать уникальным), в текстовом файле произойдут изменения: увеличатся значения хитов и хостов на 1. Теперь, допустим, тот же человек, с тем же IP заходит повторно к нам на пагу.

Перед тем, как увеличить статистику, следует порыскать в нашей базе, и если такого IP за этот день там нет, значит можно спокойно конкатенировать и то и другое, если же есть, то увеличиваем только хиты. Следует заметить, что в базе IP, кроме самих IP будут храниться дни посещения. И если любой пользователь зайдёт на сайт, допустим, через неделю, и он был единственным за это время то, следовательно база устарела и в результате из неё будут вычищены прошлые данные.

Вот собственно код:

   #!/usr/local/bin/perl
   # Объявляем переменные
   # Получаем день и номер месяца, хотя остальное не используется
   # но удалять что-либо нельзя, т.к. присвоение идёт
   # в контексте списка.
   my ($sec, $min, $hour, $day, $mon) = localtime(time);
   
   # в путь к файлу гле будут IP
   my $IpFile = "/shttps/WWW/COUNT/ip.txt";
   
   # в путь к файлу где будет лежать статистика
   my $CountFile = "/shttps/WWW/COUNT/count.txt";
   
   # ваш IP
   my $ip = $ENV{'REMOTE_ADDR'};
   
   # переменная-флаг, проверяющая IP на уникальность
   my $new = "true";
   
   # эта функция используется для обновления (перезаписи)
   # статистики и для добавления новых IP в базу
   sub WriteBase
   {
   # 1 параметр - путь для записи в файл
   # 2 параметр - отвечает за перезапись или добавление данных
   $path = $_[0];
   $bit = $_[1];
   if ($bit == 2){open COUNTFILE, ">$path"}
   elsif ($bit == 3){open COUNTFILE, ">>$path"}
   flock(COUNTFILE); # чтобы юзвери в один файл разом не
   # ломились, "блокуем" его до закрытия
   # правда у меня в винде эта фича не проходит,
   # но в UNIX должна, если нет - ПИШИТЕ!
   # если у вас Win9x - то уберите ВЕЗДЕ её
   for ($i=2; $i<=$#_; $i++)
   {
   print COUNTFILE "$_[$i]\n";
   }
   close COUNTFILE;
   }
   
   # эта функция используется для чтения данных
   sub ReadBase
   {
   
   # ей нужен только 1 парам. - путь для чтения
   $path = $_[0];
   open COUNTFILE, "<$path";
   flock(COUNTFILE)
   @count = <COUNTFILE>;
   close COUNTFILE;
   chomp($hits = @count[0]); # читаем кол-во хитов
   chomp($hosts = @count[1]); # читаем кол-во хостов
   }
   
   
   # здесь мы сравниваем сумму числа месяца и номер месяца текущих
   # с суммой, которая была записана раннее, при чьём-нибудь
   # заходе на страницу. И если прошлая запись старая, т.е.
   # допустим, это был день назад, то удаляем ко всем чертям
   # эти старые записи с IP, чтобы позволить в любой другой
   # день пользователю быть УНИКАЛЬНЫМ! Без этой проверки
   # IP хранились бы вечно (+ занимали бы место и усложняли чтение)
   # и пользователь, посетив раз эту страницу
   # уже не был бы уникальным НИКОГДА.
   
   open IP, "<$IpFile";
   flock(IP)
   while(<IP>)
   {
   if (/ (\d+)/ $1<$day+$mon)
   {
   close IP;
   unlink $IpFile; # ко всем чертям старую базу!
   ReadBase($CountFile); # читаем статистику
   WriteBase($CountFile, 2, $hits, 0); # сохраняем хиты, обнуляем хосты
   }
   }
   close IP;
   
   # проверка юзверя на уникальность
   open IP, "<$IpFile";
   flock(IP)
   while(<IP>)
   {
   if (/$ip $day+$mon/)
   {
   $new = "false"; last;
   }
   }
   close IP;
   
   # ежели уникален, то...
   if ($new eq "true")
   {
   WriteBase($IpFile, 3, "$ip $day+$mon"); # пишемся в базу
   ReadBase($CountFile); # читаем статистику
   $hits++;
   $hosts++;
   WriteBase($CountFile, 2, $hits, $hosts); # обновляем всю статистику
   
   # если юзверь еще раз ломится на пагу, то...
   else
   {
   ReadBase($CountFile); # читаем базу
   $hits++; # обламываем его с хостами, но не с хитами
   WriteBase($CountFile, 2, $hits, $hosts); # прежний хост и новый
   ReadBase($CountFile); # хит
   }
   
   # выводим всю эту инфу в своеобразный каунтер
   # мой с виду не отличить от натурального.
   # рисуем картинку 88/31 и пишем её в Бекграунд
   print "Content-type:text/html\n\n";
   print qq\ # чтобы Принты сотню раз не печатать
   <div style="pdding-left:3px;width:88px;height:31px;
   background-image:URL(cgi-bin/counter.gif);
   border-width:1px; border-style:solid; border-color:black;
   font-family:Verdana;font-size:10px;color:white;text-align:right;line-height:13px">
   $hits<br>
   $hosts<br>
   </div>\;


Как встроить счётчик
Для работы счётчика достаточно иметь любой сервер с поддержкой Perl и SSI. С помощью второго мы можем вставить наш счётчик в любое место страницы вот так:
<!--#exec cgi="counter1.pl"-->
для скрипта права 755
для текстовых файлов 666

Ну... вот вроде бы и всё :)
Для новичков, возможно, сложно, но я сам полторы недели как новичок... был. На самом деле главное понять принцип, вы и сами сможете написать что-то подобное или даже лучшее, никто вас не ограничивает. Меня ограничил лишь световой день. Perl советую всем! Он не лёгок, но две недели практики в писании скриптов вам окупятся! Удачи!

Hosted by uCoz