<% ASP на блюдечке %>. Часть 19
Система сбора и обработки статистики по посещаемости Web-сайта своими руками — 2
Какие методы увеличения популярности существуют?
Создание и подготовка базы данных
Интеграция системы в уже готовый сайт
Когда же фиксировать посещения?
Регистрация посещений – файл global.asa
Сервисные функции системы – файл Utils.asp
Главная страница системы – файл Index.asp
Основное меню системы – файл StatMain.asp
Статистика уникальных посещений (хостов) – файл Hosts.asp
Симпатичный календарь – файл Calendar.asp
Статистика всех посещений (хитов) – файл Hits.asp
Графическое представление статистики (хитов) по датам – файл HitsGraph.asp
Введение
ак мы уже не раз отмечали в предыдущих статьях серии <% ASP на блюдечке %>, популярность того или иного Интернет-ресурса Всемирной паутины обусловливается множеством самых разнообразных факторов. В предыдущей статье настоящей серии мы рассмотрели процесс создания системы сбора и обработки статистики посещений гипотетического сервера. Однако, как мы говорили, эта система может быть существенным образом доработана и оснащена целым рядом дополнительных функциональных возможностей. Это мы и собираемся предпринять в настоящей статье.
Итак, теперь нам надлежит заняться усовершенствованием системы, а именно разработкой системы фильтров хитов и хостов по датам, декодирования предыдущей страницы (страницы-referrer’a, с которой пользователь обратился к данному ресурсу). Однако прежде всего освежим в памяти разработанную нами систему и дадим определения некоторых понятий.
Популярность – что это?
бобщая, можно сказать, что популярность – это прежде всего большое количество посещений сайта. Но здесь сразу же возникает множество разнообразных вопросов: что считать посещением? откуда «пришел» пользователь? какие из страниц его больше всего заинтересовали? или как часто он заглядывал на тот или иной сайт? какова среднесуточная нагрузка на сервер? какое время суток можно считать пиковым с точки зрения посещаемости?
Согласитесь, что ответы на эти и многие другие вопросы позволят настроить Web-мастерам тот или иной ресурс Всемирной сети на конкретную аудиторию пользователей более целевым образом и тем самым добиться увеличения количества посетителей, а следовательно, и популярности.
Решению этой проблемы (усовершенствованию системы учета и анализа посещений) и посвящена настоящая статья.
Какие методы увеличения популярности существуют?
истематический анализ статистики посещений сайта — инструмент, позволяющий грамотно и своевременно среагировать на изменения посещаемости в ту или иную сторону. Под реакцией прежде всего следует понимать:
- Обновление материалов сайта. Лучше не пользоваться стандартными фразами. Имеют значение оригинальность новостей и философствование в меру способностей. Новости или хотя бы их анонсы желательно вынести на основную страницу. Для оригинальности можно писать не только дату обновления, но и время с точностью до минуты.
- Обмен баннерами с сайтами такой же популярности (не ниже) с помещением на главные страницы на специальном и видном месте.
- Сотрудничество с популярными сайтами. Например, можно договориться на размещение на главных страницах рекламных баннеров сроком до 1 месяца — больше не имеет смысла. Прошел месяц — ищите другой сайт-партнер. Таким образом вы будете привлекать постоянных посетителей сайта-партнера, которые, возможно, станут и вашими постоянными посетителями.
- Баннерную рекламу. Эффективно, если ваш баннер имеет CTR (коэффициент полезного действия) свыше 4%. Баннер меняйте с периодичностью 1-2 месяца.
- Устраивайте на сайте интересные викторины. Желательно с призами.
- Настройте вашу почтовую программу, чтобы в конце письма приписывался адрес вашего сайта с кратким описанием. Эффективно в том случае, если вы часто посылаете письма большому количеству людей.
- Производите регулярную кампанию по почтовой рассылке информации о сайте большому количеству потенциально заинтересованных клиентов по электронной почте с помощью специальных программ (Bulk Mailing).
- Неназойливая и интригующая реклама, например, с периодичностью раз в неделю, на нескольких популярных форумах и/или чатах тоже сыграет вам на руку. Однако если посетители форума или чата отзываются на рекламу негативно, лучше прекратить, иначе приобретете дурную репутацию.
- Индексация сайте в разнообразных поисковых машинах как в зоне .ru (Rambler, Yandex, Aport…), так и в зоне .com (AltaVista, Yahoo, HotBot, Lycos…) для успешного нахождения вашего сайта этими поисковыми машинами.
Этот список можно продолжать, однако мы перечислили основные методы улучшения посещаемости.
Внесем ясность
ействительно, прежде чем приступить к работе, надо разобраться и дать определения нескольким ключевым понятиям, связанным с посещениями и посещаемостью.
Посещение — однократное пребывание пользователя на том или ином ресурсе. Причем это может быть как один и тот же пользователь, так и несколько разных. Другими словами, посещение иногда называют «хитом» (от английского hit).
Уникальное посещение — однократное пребывание данного пользователя на том или ином ресурсе. Причем речь идет о посещении ресурса именно данным пользователем. Компьютеры разных пользователей отличаются друг от друга IP-адресами. Именно это обстоятельство и используется при вычислении уникальных посещений, или так называемых хостов (от английского host).
Клиент — под клиентом здесь подразумевается тип, версия браузера и операционная система, с помощью которого и под управлением которой было осуществлено посещение или уникальное посещение ресурса.
Реферер (referer) — адрес Всемирной сети, где пользователь «находился» непосредственно до осуществления посещения или уникального посещения данного ресурса. Это, как правило, поисковые машины. Таким образом, можно определять эффективность той или иной поисковой машины или ссылки во Всемирной сети применительно именно к данному сайту.
Страна принадлежности хоста — страна, в доменной зоне которой находится тот или иной пользователь (вычисляется из IP-адреса путем декодирования его в доменное имя).
Организация работ
режде всего представим себе, что же нам предстоит сделать для фиксирования всевозможных посещений нашего гипотетического Web-сайта.
Во-первых, нам необходимо регистрировать (записывать в базу данных) все уникальные посещения (хосты) нашего сайта с учетом IP-адресов и «Клиентов».
Во-вторых, то же самое нам придется проделывать и с обычными посещениями (хитами), причем делать это подневно, фиксируя при этом количество посещений за каждый день. Это позволит нам в дальнейшем перейти и к большим единицам измерения времени, как то: недели, месяцы, годы. Хотя в общем случае, когда в этом есть необходимость, можно регистрировать хиты и ежечасно. Но это может иметь смысл исключительно в применении к сайтам с очень большим количеством хитов.
В-третьих, необходимо разработать подсистему контроля за доступом статистической информации — во избежание несанкционированного доступа к ней.
Далее требуется разработать дружественный интерфейс, позволяющий пользователям просматривать желаемую статистику в удобной и читабельной форме (этот пункт имеет массу вариантов развития — вплоть до генерации отчетов в формате MS Excel).
Создание и подготовка базы данных
ля организации хранения данных о посещениях нам понадобятся две таблицы. В первой мы будем хранить хиты наших пользователей, а во второй — хосты.
Таблица хитов будет хранить количество хитов по дням следующим образом: .
Таблица хостов будет хранить количество хостов по датам посещения и с учетом IP-адреса, Referer’а и Клиента следующим образом: .
Для организации удобного встраивания системы в уже существующие сайты рекомендуется спланировать еще одну таблицу для организации хранения имен и паролей пользователей, которым будет делегировано право просмотра и анализа статистики по посещениям данного ресурса: .
Далее необходимо прописать нашу базу данных в соответствующем разделе источников данных системы. Для этого проделайте следующее:
- Запустите программу — конфигуратор источников данных (Data Sources ODBC) — Start->Settings->Control Panel->Administrative Tools->Data Sources ODBC.
- Перейдите во вкладку System DSN и создайте новый источник данных, нажав на Add…
- В появившемся списке драйверов выберите драйвер баз данных — Microsoft SQL Server и нажмите на Next.
- В строке Data Source Name задайте имя нашей базы данных — в данном случае SiteStat (это имя, по которому мы в дальнейшем будем к ней обращаться).
- В строке Server укажите сервер, к которому будет осуществлено подключение, и нажмите на Next.
- Выберите режим аутентификации With SQL Server…, задайте имя пользователя и пароль для подключения к SQL-серверу, определите протокол связи с сервером (кнопка Client Configuration — TCP/IP) и два раза нажмите на Next, после чего нажмите на Finish.
- Вы увидите статистику о проделанных действиях, а для проверки источника данных можете воспользоваться кнопкой Test Data Source.
- Перед вами появится строка в списке источников данных в вашей системе.
Теперь, когда база данных готова, можно переходить к созданию и самой системы статистики.
Интеграция системы в уже готовый сайт
ело в том, что сама по себе система сбора и анализа статистики не имеет смысла. Посудите сами, кому нужен сайт, предназначенный исключительно для сбора и обработки посещаемости? Поэтому ключевым моментом в разработке такой системы является в первую очередь простота и удобство ее встраивания в уже существующий ресурс Всемирной компьютерной сети. Следовательно, моментам, связанным с упрощением встраивания системы в уже готовые сайты, надо уделить особое внимание.
Когда же фиксировать посещения?
где это делать? На эти, казалось бы, совсем простые вопросы мы пока не дали ответов. Давайте разберемся. Во-первых, это нужно делать всегда при заходе (визите) пользователя на главную страничку сайта. Однако, как правило, ветвь сбора и обработки статистики принадлежит самому сайту. Надо отметить, что такая практика весьма сомнительна, поскольку посещение самой системы статистики также будет приводить к регистрации последнего в системе, что будет искажать результаты статистики посещений. Но кроме этого можно, например, вести статистику посещаемости по различным страничкам, причем делать это раздельно. Для простоты изложения и восприятия материала в данной статье давайте ограничимся случаем регистрирования захода на главную страничку сайта. Наиболее удобным в этом плане является файл global.asa, который, как нам известно, содержит четыре метода, отрабатывающих по четырем событиям соответственно. Давайте повторим их.
Что такое Global.asa
так, Global.asa позволяет выполнять определенные скрипты в начале работы клиентской сессии или при инициализации IIS. Более того, допустимо использовать множественные файлы Global.asa. Однако следует помнить, что ASP-скрипт ищет самый близкий (расположенный в том же каталоге) файл Global.asa и использует именно его.
По сути, этот файл может содержать четыре скрипта: первый будет выполняться при инициализации службы IIS/PWS (Application_OnStart), второй — при остановке службы IIS/PWS (Application_OnEnd) (обычно эти первые два скрипта отрабатывают в процессе перезагрузки компьютера), и еще два скрипта выполняются дополнительно при инициализации сессии пользователя (Session_OnStart) и по ее окончании (Session_OnEnd). Данная схема очень сильно напоминает пары «конструктор-деструктор». Неспроста всякая переменная, которая должна быть использована (например, в текущей сессии), может быть инициализирована в Session_OnStart с тем, чтобы быть использованной в процессе работы сессии, уничтожается (обнуляется) же она в Session_OnEnd.
Global.asa не может содержать тэгов HTML. Недопустимо использование JavaScript. Не рекомендуется писать файл Global.asa с помощью каких-либо HTML-редакторов, для этого лучше использовать NotePad. И еще один совет: прежде чем вставлять скрипт в файл Global.asa, попробуйте его в работе в обычном ASP-файле.
<OBJECT RUNAT=Server SCOPE=Session ID=Tool1 PROGID="MSWC.Tools"> </OBJECT> <SCRIPT LANGUAGE = "VBScript" RUNAT="Server"> Sub Session_OnStart Dim strUserLogon Dim StrUserSecurity ' Эти переменные сессии будут держать ' значения имени пользователя ( logon) и права его доступа strUserLogon = Request.ServerVariables("USER_LOGON" ) strUserSecurity = "PUBLIC" End Sub Sub Session_OnEnd ' Этот код уничтожает компонент Tools для текущей сессии. Set Tool1 = Nothing 'А этот обнуляет переменные сессии. strUserLogon = "" strUserSecurity = "" ‘ Внимание!: Данный код применять в этом смысле совсем не обязательно ' так как объекты будут выгружены из памяти Web-сервером ' автоматически по закрытии текущей сессии. End Sub </SCRIPT>
Регистрация посещений – файл global.asa
нашей точки зрения интерес представляет метод Session_OnStart, поскольку именно он отрабатывает при заходе на сайт (при порождении сессии). Итак, нам необходимо вставить в тело этого метода код, который будет осуществлять:
- Запись в таблицу хитов всех посещений в подневном режиме.
- Запись в таблицу хостов уникальных хостов с фиксацией даты посещения, клиента, IP-адреса и Referer’а посетителя.
<SCRIPT LANGUAGE = VBScript RUNAT=Server> <!-- Metadata type="typelib" File="c:\program files\common files\system\ado\msado15.dll" --> </SCRIPT> <OBJECT RUNAT=Server SCOPE=Session ID=MyInfo PROGID="MSWC.MyInfo"></OBJECT> <script language="vbscript" runat=server> Sub Application_OnStart Session.TimeOut = 1 End Sub Sub Application_OnEnd Session.Abandon End Sub Sub Session_OnStart Session.TimeOut = 1 dim strConn, objConn dim dsn,conn,rs,sql …
Объявим переменные, посредством которых будем осуществлять соединение с базой данных:
… dsn = "DSN=SiteStat; UID=SiteStat;PWD=SiteStat;database=SiteStat" set conn = server.createobject("adodb.connection") set rs = server.createobject("adodb.recordset") conn.open dsn …
Получим IP-адрес пользователя, его «клиент» и реферер:
… ' Insert incoming IP & Client dim IP, Browser IP = Request.ServerVariables("REMOTE_ADDR") Browser = Request.ServerVariables("HTTP_USER_AGENT") Referer = Request.ServerVariables("HTTP_REFERER") …
Добавим запись в таблицу хостов, если IP-адреса с таким значением там не обнаружено:
… sql = "select * from Hosts where IPAddress='" & IP & "'" rs.open sql, conn, adOpenStatic, adLockOptimistic if rs.EOF then rs.addnew rs("IPAddress") = IP rs("HTTPClient") = Browser rs("Referer") = Referer rs.update end if rs.close …
Вычислим сессионную переменную с суммарным количеством хитов за все время существования сайта для отображения на главной страничке:
… ' --------------------------------- sql = "select SUM(Hits) As HitsNum from Hits" rs.open sql, conn Session("Hits") = rs("HitsNum") rs.close …
Увеличим значение хитов за текущий день в таблице хитов. Здесь используются операторы работы с датами языка Transact-SQL. Для того чтобы нижеследующий код был вполне понятен, приведем краткую справку:
Day(datetime) – возвращает значение дней с начала месяца для заданной даты datetime. Month(datetime) – возвращает значение месяцев с начала года для заданной даты datetime. Year(datetime) – возвращает значение лет для заданной даты datetime. GetDate() – возвращает текущую дату и время на сервере. … ' --------------------------------- sql = "SELECT * FROM Hits WHERE Day(DayDate) = DAY(Getdate()) " sql = sql & "AND MONTH(DayDate) = MONTH(GetDate()) AND YEAR(DayDate) = YEAR(GetDate())" rs.open sql, conn If NOT rs.EOF THEN sql = "UPDATE Hits SET Hits = Hits + 1 WHERE Day(DayDate) = DAY(Getdate()) " sql = sql & "AND MONTH(DayDate) = MONTH(GetDate()) AND YEAR(DayDate) = YEAR(GetDate())" conn.execute(sql) Else sql = "INSERT INTO Hits (DayDate, Hits) VALUES (GETDATE(), 1)" conn.execute(sql) End If rs.close …
Вычислим сессионную переменную с суммарным количеством хостов за все время существования сайта для отображения на главной страничке
… ' Count hosts --------------------- sql = "select COUNT(*) AS HostsNum FROM Hosts" rs.open sql, conn, adOpenStatic, adLockOptimistic Session("Hosts") = rs("HostsNum") rs.close …
Закроем соединение с базой данных и обнулим переменные
… ' --------------------------------- set rs = nothing conn.close set conn = nothing End Sub Sub Session_OnEnd Session.Abandon End Sub </script>
Сервисные функции системы – файл Utils.asp
режде чем мы начнем, целесообразно вынести сервисные функции в отдельный файл, который мы будем «включать» в код по мере необходимости. Это избавит нас от повторений часто используемых функций и частей кода:
<SCRIPT LANGUAGE = VBScript RUNAT=Server> <!-- Metadata type="typelib" File="c:\program files\common files\system\ado\msado15.dll" --> </SCRIPT> …
Функции подключения к базе данных и отключения от нее.
… <% option explicit response.buffer=true Response.Buffer = true dim strConn, objConn dim dsn,conn,rs,sql, conn1, rs1, sql1 dsn = "DSN=SiteStat; UID=SiteStat;PWD=SiteStat;database=SiteStat" Sub Connect() set conn = server.createobject("adodb.connection") set rs = server.createobject("adodb.recordset") conn.open dsn End Sub Sub Connect1() set conn1 = server.createobject("adodb.connection") set rs1 = server.createobject("adodb.recordset") conn1.open dsn End Sub Sub Close() rs.close set rs = nothing conn.close set conn = nothing End Sub Sub Close1() rs1.close set rs1 = nothing conn1.close set conn1 = nothing End Sub …
Функция контроля доступа вызывается в начале каждой странички, информацию на которой по тем или иным признакам можно считать доступной только для определенного круга лиц. В случае несовпадения константы с сессионной переменной, инициализируемой при входе в систему, пользователь перенаправляется на страничку с сообщением об ошибке доступа .
… Sub secure_general() If session("status") <> "admin" Then Response.Redirect "error.htm" End If End Sub %>
Главная страница системы – файл Index.asp
еперь настала пора изготовить форму ввода имени пользователя и пароля, замкнуть форму на себе самой и, обработав пользовательский ввод уже известным вам из предыдущих серий настоящей статьи образом, перенаправить пользователя на страничку с основным меню системы:
<!--#include file="utils.asp"--> <% dim useraction,username,password,forumid …
Анализ пользовательского ввода. Из введенного имени пользователя и пароля удаляются пробелы и производится выборка из таблицы пользователей системы с совпадением имени и пароля с заданными. В случае совпадения инициализируется сессионная переменная, делигирующая доступ к остальным страничкам статистики; в случае несовпадения выводится сообщение об ошибке.
… useraction = request("action") Select Case userAction Case "login" username = Trim (request.form("username")) password = Trim (request.form("password")) Call Connect() sql="select * from StatUsers where username='"&username&"' and password='"&password&"'" rs.open sql,conn If rs.eof AND rs.bof Then Response.Write "<b>Проверьте правильность ввода имени и/или пароля</b><br><br>" Else Session("status") = "admin" Response.Redirect "StatMain.asp" End If Call Close() End Select %> …
Реализация формы ввода имени и пароля выглядит следующим образом:
… <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <link rel="stylesheet" href="grc.css" type="text/css"> <title>SiteStat - Администрирование</title> </head> <body> <div align="center"> <h2><p align="center">Статистика посещений Web-сайта <a href="http://www.SiteStat.ru">www.SiteStat.ru</a></p></h2> <hr> <p>Введите Login и пароль доступа к системе статистики</p> <table border=1 bgcolor = "#FFFFeF" width="270"> <form action="index.asp?action=login" method="post"> <tr><td colspan=2 align = center>Администратор системы</td></tr> <tr><td>Имя:</td><td> <input type="text" name="username" size=20 maxlength=20> </td></tr> <tr><td>Пароль:</td><td> <input type="password" name="password" size=20 maxlength=20> </td></tr> <tr><td colspan=2 align=center><input type="submit" name="submit" value="Вход"></td></tr> </form> </table> <br> <hr> <a href="javascript:history.back(-1)">Назад</a> | <a href="../main.asp">Главная страница сайта</a> </div> </body> </html>
Основное меню системы – файл StatMain.asp
осле того как процедура идентификации пользователя пройдена, можно реализовать страничку с основным меню системы, с которой будут осуществлены переходы в режим просмотра данных по хостам, по хитам и в режим графического просмотра динамики хитов за интервалы времени (по дням и по месяцам):
<!--#include file="utils.asp"--> <% Call secure_general() %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <link rel="stylesheet" href="grc.css"> <title>ASP на блюдечке.Часть 18.Статистика посещений</title> </head> <body> <h2><p align="center">Статистика посещений Web-сайта <a href="http://www.SiteStat.ru">www.SiteStat.ru</a></p></h2> <hr> <div align="center"> <h3>Выберите режим работы <br><br></h3> <p><a href="Hosts.asp">Статистика уникальных посещений Web-сайта (хосты)</a></p> <p><a href="Hits.asp">Статистика всех посещений Web-сайта (хиты)</a></p> <p><a href="HitsGraph.asp">Графическое представление хитов по датам</a></p> <hr> <p> <a href="javascript:history.back(-1)">Назад</a> | <a href="../main.asp">Главная страница</a> </p> </div> </body> </html>
Статистика уникальных посещений (хостов) – файл Hosts.asp
ыборка статистики по уникальным посещениям основана на таблице Hosts и содержит те ее значения, которые соответствуют дате, задаваемой посредством интерфейса пользователя, и отсортированы по дате начиная с самого свежего хоста. Для реализации последнего нам потребуется разработать фильтр хостов по дням. Сделать это лучше всего в дополнительном, включаемом файле, который необходимо включить в тело нижеследующего модуля Hosts.asp:
<!--#include file="utils.asp"--> <% Call secure_general() %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <link rel="stylesheet" href="grc.css"> <title>ASP на блюдечке. Часть 19. Статистика посещений</title> </head> <body> <% Dim DayPassed, MonthPassed, YearPassed, DateDisplayed, adSQL … Опросим переменные, содержащие дату, хосты по которой требуется показать … DayPassed = Request("DayPassed") MonthPassed = Request("MonthPassed") YearPassed = Request("YearPassed") Session("DisplayDate") = DayPassed & "." & MonthPassed & "." & YearPassed …
Построим SQL-запрос — фильтр наших данных
… If DayPassed <> "" AND MonthPassed <> "" AND YearPassed <> "" Then adSQL = " WHERE DAY(DateVisited) = " & DayPassed & " AND MONTH(DateVisited) = " & MonthPassed adSQL = adSQL & " AND YEAR(DateVisited) = " & YearPassed DateDisplayed = CStr(DayPassed) & "." & CStr(MonthPassed) & "." & CStr(YearPassed) Else adSQL = " WHERE DAY(DateVisited) = DAY(GETDATE()) AND MONTH(DateVisited) = MONTH(GETDATE())" adSQL = adSQL & " AND YEAR(DateVisited) = YEAR(GETDATE())" DateDisplayed = "сегодня - " & Date() Session("DisplayDate") = Day(Date()) & "." & Month(Date()) & "." & Year(Date()) End If call connect() sql="SELECT COUNT(*) AS HostsNum FROM HOSTS" & adSQL rs.open sql,conn %> <h2><p align="center">Статистика посещений Web-сайта <a href="http://www.centpart.ru">www.centpart.ru</a></p></h2> <hr> <div align="center"> <h3>Выборка по уникальным заходам на сайт за <% Response.Write " за " & DateDisplayed %> (всего <% = rs("HostsNum")%> хост(ов))</h3> …
Вот сюда и включим файл нашего компонента-календаря
… <!--#include file="calendar.asp"--> <br> <table border=2 width=960 align=center> <tr align = left> <td colspan = 2 width="170"><h4>Дата посещения</h4></td> <td colspan = 2 width="120"><h4>IP-адрес</h4></td> <td colspan = 2 width="220"><h4>Реферер</h4></td> <td colspan = 2 width="450"><h4>HTTP Клиент (браузер)</h4></td> </tr> <% rs.close sql="SELECT * FROM Hosts " & adSQL & " ORDER BY DateVisited DESC" rs.open sql,conn Do While NOT rs.EOF %> <tr align = left> <td colspan = 2><% =rs("DateVisited") %></td> <td colspan = 2><% =rs("IPAddress") %></td> <td colspan = 2><a href="><% =rs("Referer") %>"><% =rs("Referer") %></a></td> <td colspan = 2><% =rs("HTTPClient") %></td> <% rs.MoveNext Loop %> </tr> <% call close() %> </table> <br> <p> <a href="javascript:history.back(-1)">Назад</a> | <a href="StatMain.asp">Главная страница статистики</a> </p> </div> </body> </html>
Симпатичный календарь – файл Calendar.asp
еперь, пожалуй, настала пора разобраться с интерфейсом даты, хосты по которой мы, собственно, и будем предоставлять пользователям. Вопреки традиции откажемся от использования формы, в которую необходимо «вбить» значения дня, месяца и года, а реализуем гораздо более удобный элемент управления, похожий на обычный настенный календарь. Страничка со списком хостов с таким календарем (встроенным, как мы описали выше) будет выглядеть гораздо привлекательнее и удобнее ().
Работает такой компонент очень просто. По умолчанию он отображает текущую дату. Дни месяца выполнены в виде линков, которые приводят к показу хостов соответствующей даты (что, собственно, и реализует SQL-фильтр по дате в модуле Hosts.asp). Кроме того, существуют линки, переходящие от месяца к месяцу вперед и назад. Для реализации такого компонента нам для начала потребуется четыре функции обработки дат. Давайте рассмотрим их:
' Функция подсчета количества дней в месяце Function GetDaysInMonth(iMonth, iYear) Dim dTemp dTemp = DateAdd("d", -1, DateSerial(iYear, iMonth + 1, 1)) GetDaysInMonth = Day(dTemp) End Function ' Функция подсчета дня начала месяца Function GetWeekdayMonthStartsOn(dAnyDayInTheMonth) Dim dTemp dTemp = DateAdd("d", -(Day(dAnyDayInTheMonth) ), dAnyDayInTheMonth) GetWeekdayMonthStartsOn = WeekDay(dTemp) End Function ' Функция-декрементор месяцев, которая будет отрабатываться при переходе к предыдущему месяцу Function SubtractOneMonth(dDate) SubtractOneMonth = DateAdd("m", -1, dDate) End Function ' Функция-инкрементор месяцев, которая будет отрабатываться при переходе к следующему месяцу Function AddOneMonth(dDate) AddOneMonth = DateAdd("m", 1, dDate) End Function
Далее мы просто должны прочитать дату из сессионной переменной (она может быть текущей, а может задаваться пользователем). После этого, прежде чем рисовать таблицу со значениями, требуется вычислить параметры для цикла, а именно: количество дней в месяце и день недели, с которого начинается месяц. А дальше все очень просто:
<% Dim dDate ' Дата показа календаря Dim iDIM ' Дней в месяце Dim iDOW ' День недели, с которого начинается месяц Dim iCurrent ' Текущий день месяца Dim iPosition ' Текущая позиция в таблице Dim DayStr, MonStr ' День и месяц в правильном формате ( с 0 в начале, если день однозначен) Response.write Session("DisplayDate") dDate = CDate(Session("DisplayDate")) …
Получим значение дней в месяце и дня недели, с которого он начинается
… iDIM = GetDaysInMonth(Month(dDate), Year(dDate)) iDOW = GetWeekdayMonthStartsOn(dDate) %> <!-- Внешняя таблица для рисования контура--> <TABLE BORDER=5 CELLSPACING=0 CELLPADDING=0> <TR><TD> <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=1 BGCOLOR=#99CCFF> <TR> <TD BGCOLOR=#B4AF94 ALIGN="center" COLSPAN=7> <TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0> <TR> …
Построим строку и передадим ее модулю Hosts.asp, где в качестве параметров передадим день, месяц и год даты, данные по которой необходимо представить пользователю. Как видите, передается строка, в которой переменным DayPassed, MonthPassed и YearPassed присваиваются значения дня, месяца и года предыдущего и последующего месяцев соответственно, в зависимости от линка, которым воспользуется пользователь (дата генерируется функциями, возвращающими значение следующего и предыдущего месяцев):
… <TD ALIGN="right"><A HREF="Hosts.asp?DayPassed=<%=Day(SubtractOneMonth(dDate))%>&MonthPassed=<%=Month(SubtractOneMonth(dDate))%> &YearPassed=<%=Year(SubtractOneMonth(dDate))%>"><FONT COLOR=#5c0000 SIZE="-1"><<</FONT></A></TD> <TD ALIGN="center"><FONT COLOR=#5c0000><B><%= MonthName(Month(dDate)) & " " & Year(dDate) %></B></FONT></TD> <TD ALIGN="left"><A HREF="Hosts.asp?DayPassed=<%= Day(AddOneMonth(dDate)) %>&MonthPassed=<%= Month(AddOneMonth(dDate)) %>&YearPassed=<%= Year(AddOneMonth(dDate)) %>"><FONT COLOR=#5c0000 SIZE="-1">>></FONT></A></TD> </TR> </TABLE> </TD> </TR> <TR> <TD ALIGN="center" BGCOLOR=#B4AF94><FONT COLOR=#5c0000><B>Пн.</B></FONT></TD> <TD ALIGN="center" BGCOLOR=#B4AF94><FONT COLOR=#5c0000><B>Вт.</B></FONT></TD> <TD ALIGN="center" BGCOLOR=#B4AF94><FONT COLOR=#5c0000><B>Ср.</B></FONT></TD> <TD ALIGN="center" BGCOLOR=#B4AF94><FONT COLOR=#5c0000><B>Чт.</B></FONT></TD> <TD ALIGN="center" BGCOLOR=#B4AF94><FONT COLOR=#5c0000><B>Пт.</B></FONT></TD> <TD ALIGN="center" BGCOLOR=#B4AF94><FONT COLOR=#5c0000><B>Сб.</B></FONT></TD> <TD ALIGN="center" BGCOLOR=#B4AF94><FONT COLOR=#5c0000><B>Вск.</B></FONT></TD> </TR> <% …
Заполним часть первого ряда пустыми ячейками, если месяц начинается не с первого дня недели
… If iDOW <> 1 Then Response.Write vbTab & "<TR>" & vbCrLf iPosition = 1 Do While iPosition < iDOW Response.Write vbTab & vbTab & "<TD BGCOLOR=#E0DDCE> </TD>" & vbCrLf iPosition = iPosition + 1 Loop End If …
Далее заполним нашу таблицу днями, подсветим текущий
… iCurrent = 1 iPosition = iDOW Do While iCurrent <= iDIM ' Если мы в начале ряда, пишем tr If iPosition = 1 Then Response.Write vbTab & "<TR>" & vbCrLf End If ' Подсветим текущий день If iCurrent = Day(dDate) Then Response.Write vbTab & vbTab & "<TD BGCOLOR=#B4AF94><FONT COLOR=#5c0000 SIZE=""-1""><B>" & iCurrent & "</B></FONT><BR></TD>" Else DayStr = CStr(iCurrent) If Len(DayStr) = 1 Then DayStr = "0" & DayStr MonStr = CStr(Month(dDate)) If Len(MonStr) = 1 Then MonStr = "0" & MonStr …
Аналогичным образом формируется и ссылка на конкретную дату (конкретный день месяца)
… Response.Write vbTab & vbTab & "<TD BGCOLOR=#E0DDCE><A HREF='Hosts.asp?DayPassed=" & DayStr & "&MonthPassed=" & MonStr & "&YearPassed=" & Year(dDate) & "'><FONT SIZE=""-1"">" & iCurrent & "</FONT></A><BR></TD>" End If ' Если мы в конце ряда, пишем /tr If iPosition = 7 Then Response.Write vbTab & "</TR>" & vbCrLf iPosition = 0 End If iCurrent = iCurrent + 1 iPosition = iPosition + 1 Loop …
Заполним остаток ячеек дней месяца пустотами
… If iPosition <> 1 Then Do While iPosition <= 7 Response.Write vbTab & vbTab & "<TD BGCOLOR=#E0DDCE> </TD>" & vbCrLf iPosition = iPosition + 1 Loop Response.Write vbTab & "</TR>" & vbCrLf End If %>
Статистика всех посещений (хитов) – файл Hits.asp
ыборка статистики по всем посещениям основана на таблице Hits и содержит выборку по дням всех ее значений, отсортированных по дате начиная с самого свежего хита:
<!--#include file="utils.asp"--> <% Call secure_general() %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <link rel="stylesheet" href="grc.css"> <title>ASP на блюдечке. Часть 18.Статистика посещений</title> </head> <body> <% call connect() sql="SELECT COUNT(*) AS DaysNum, SUM(Hits) As HitsNum FROM Hits" rs.open sql,conn %> <h2><p align="center">Статистика посещений Web-сайта <a href="http://www.SiteStat.ru">www.SiteStat.ru</a></p></h2> <hr> <div align="center"> <h3>Выборка по всем заходам на сайт (по <% = rs("HitsNum") %> хитам, произошедшим за <% = rs("DaysNum")%> дней)</h3> <br> <table border=2 width=830 align=center> <tr align = left> <td colspan = 2 width="170"><h4>День посещения</h4></td> <td colspan = 2 width="500"><h4>Количество хитов</h4></td> </tr> <% rs.close sql="SELECT * FROM Hits ORDER BY DayDate DESC" rs.open sql,conn Do While NOT rs.EOF %> <tr align = left> <td colspan = 2> <% =rs("DayDate") %> </td> <td colspan = 2> <% =rs("Hits") %> </td> <% rs.MoveNext Loop %> </tr> <% call close() %> </table> <br> <p> <a href="javascript:history.back(-1)">Назад</a> | <a href="StatMain.asp">Главная страница статистики</a> </p> </div> </body> </html>
Графическое представление статистики (хитов) по датам – файл HitsGraph.asp
ыборка статистики по всем посещениям основана на таблице Hits и содержит выборку по дням всех ее значений, отсортированных по дате начиная с самого свежего хита. Страничка реализована в двух режимах: режим просмотра по дням и режим просмотра по месяцам. В каждом из режимов помимо численной информации представлена и графическая информация в виде горизонтальных и вертикальных столбиков соответственно:
<!--#include file="utils.asp"--> <% DIM ScaleFactor, I, MonthStr, MaxMonthHits, Month, Year Call secure_general() %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <link rel="stylesheet" href="grc.css"> <title>Централ Партнершип - статистика посещений</title> </head> <body> …
Для начала определим суммарное количество хитов и количество дней, за которые ведется статистика:
… <% call connect() sql="SELECT COUNT(*) AS DaysNum, SUM(Hits) As HitsNum FROM Hits" rs.open sql,conn %> <h2><p align="center">Статистика посещений Web-сайта <a href="http://www.SiteStat.ru">www.SiteStat.ru</a></p></h2> <hr> <div align="center"> <h3>Выборка по всем заходам на сайт (по <% = rs("HitsNum") %> хитам, произошедшим за <% = rs("DaysNum")%> дней)</h3> <% rs.close …
Затем опросим переменную режима работы и сформируем форму в зависимости от ее значения. Обратите внимание на то, каким образом реализована обработка нажатия на радиокнопки. Submit формы происходит не по нажатию на кнопку Submit (которой в данном случае вообще нет), а по непосредственному переключению режима. Это достигается посредством встраивания кода "javascript:document.ViewStyleForm.submit();" в функцию обработки нажатия на радиокнопку OnClick:
… Dim VS VS = request("vs") If VS = "" THEN VS = 1 %> <table> <tr><td> <form name="ViewStyleForm" method="post" action="HitsGraph.asp"> <input type="radio" name="vs" value="1" OnClick="javascript:document.ViewStyleForm.submit();" <% If VS = 1 THEN Response.Write "checked" %> >Просмотр по дням<br> <input type="radio" name="vs" value="2" OnClick="javascript:document.ViewStyleForm.submit();" <% If VS = 2 THEN Response.Write "checked" %> >Просмотр по месяцам </form> </td></tr> </table> …
Далее в зависимости от выбранного режима работы:
… <% If VS = 1 Then Response.Write "<table border=2 width=830 align=center><tr align = left>" Response.Write "<td colspan = 2 width='170'><h4>Дата посещения</h4></td>" Response.Write "<td colspan = 2 width='660'><h4>Хитов</h4></td></tr>" sql="SELECT MAX(Hits) AS MaxHits FROM Hits" rs.open sql,conn ScaleFactor = 650 / rs("MaxHits") rs.close sql="SELECT * FROM Hits ORDER BY DayDate DESC" rs.open sql,conn I = 1 Do While NOT rs.EOF Response.Write "<tr align = left><td colspan = 2>" Response.Write rs("DayDate") Response.Write "</td><td colspan = 2>" Response.Write "<img src = images/char"& I &".gif width=" & rs("Hits") * ScaleFactor & " height=10>" Response.Write " " & rs("Hits") Response.Write "</td>" I = I + 1 IF I = 11 Then I = 1 rs.MoveNext Loop Response.Write "</tr>" call close() Else %> <table cellspacing=0 cellpadding=0 width=830 height=550 style="BORDER-RIGHT: rgb(0,0,0) 0px outset; BORDER-TOP: rgb(0,0,0) 0px outset; BORDER-LEFT: rgb(128,128,128) 1px outset; BORDER-BOTTOM: rgb(128,128,128) 1px outset"vAlign=top width="830" height=1> <tr align="left"> <td width="5"> </td> …
Необходимо сосчитать количество хитов, произошедших за месяц. Для этого создадим вычисляемое поле, однозначно идентифицирующее совокупность записей в таблице хитов за месяц. Сделать это очень просто — прибавив к значению года значение месяца, умноженное на 12. Далее будем оперировать этим значением для реализации поиска количества месяцев, вычисления суммы хитов за месяц и фактора масштабирования, для корректного отображения графических элементов на экране независимо от фактических значений:
… <% MaxMonthHits = 0 sql = "SELECT DISTINCT YEAR(DayDate) * 12 + MONTH(DayDate) AS UniqueMonth FROM Hits" rs.open sql,conn Do While NOT rs.EOF Call Connect1() sql1="SELECT Hits, MONTH(DayDate) AS Month, YEAR(DayDate) AS Year " sql1 = sql1 & " FROM Hits WHERE (YEAR(DayDate) * 12 + MONTH(DayDate)) = " sql1 = sql1 & rs("UniqueMonth") & " ORDER BY DayDate" rs1.open sql1,conn1 MonthStr = CStr(rs1("Month")) & "." & CStr(rs1("Year")) Call Close1() Call Connect1() sql1="SELECT SUM(Hits) AS MonthHits FROM Hits WHERE YEAR(DayDate) * 12 + MONTH(DayDate) = " & rs("UniqueMonth") rs1.open sql1,conn1 If MaxMonthHits < rs1("MonthHits") Then MaxMonthHits = rs1("MonthHits") Call Close1() rs.MoveNext Loop rs.close I = 1 ScaleFactor = 550 / MaxMonthHits sql = "SELECT DISTINCT YEAR(DayDate) * 12 + MONTH(DayDate) AS UniqueMonth FROM Hits" rs.open sql,conn Do While NOT rs.EOF Call Connect1() sql1="SELECT Hits, MONTH(DayDate) AS Month, YEAR(DayDate) AS Year " sql1 = sql1 & " FROM Hits WHERE (YEAR(DayDate) * 12 + MONTH(DayDate)) = " sql1 = sql1 & rs("UniqueMonth") & " ORDER BY DayDate" rs1.open sql1,conn1 Month = rs1("Month") Year = rs1("Year") Call Close1() Call Connect1() sql1="SELECT SUM(Hits) AS MonthHits FROM Hits WHERE YEAR(DayDate) * 12 + MONTH(DayDate) = " & rs("UniqueMonth") rs1.open sql1,conn1 Response.Write "<td width='2' valign='bottom' align='left'>" Response.Write "<img src = images/char" & I & ".gif width=20 height=" Response.Write rs1("MonthHits") * ScaleFactor & "></td>" Response.Write "<td width='5' valign='bottom' align='left'>" Response.Write "<img src = images/Months/" & Month & ".gif </td>" Call Close1() I = I + 1 If I = 11 Then I = 1 rs.MoveNext Loop rs.close %> <td width=100%> </td> </tr> </table> <% End If %> </table> <br> <p> <a href="javascript:history.back(-1)">Назад</a> | <a href="StatMain.asp">Главная страница статистики</a> </p> </div> </body> </html>
Заключение
ассмотренная нами система сбора и анализа статистики по посещению Интернет-ресурса достаточно удобна и позволяет отслеживать основную информацию по динамике посещений. Благодаря модульной реализации система легко встраиваема в сайт практически любой степени сложности. Среди новых возможностей нужно отметить регистрацию реферера пользователя и наличие компонент-календаря. Последний, в частности, может быть с успехом применен не только в системах сбора и обработки информации, но и везде, где необходим удобный и наглядный фильтр по дате именно в виде календаря. Благодаря модульной реализации встраивание его в любую такую систему займет не более 10 минут.
Генерацией отчетов в привычной для пользователя форме, усовершенствованием графического интерфейса для аналитической части системы и т.д. мы займемся в последующих сериях настоящей статьи.
В заключение хотелось бы отметить, что система анализа статистики обращений является достаточно мощным и удобным инструментом, позволяющим пользователю получить доступ к информации, качественным образом повышающей посещаемость того или иного Интернет-ресурса, независимо от характера и структуры последнего.КомпьютерПресс 4'2002