1. Введение
2. Инструменты сбора статистики
3. Скрипт для сбора статистики из log-файлов
4. Заключение
Статистика – это наука, требующая внимания, времени и терпения. Но то, что в Интернете (а в частности, в Рунете) называют «статистикой веб-сайтов», к науке пока отношение имеет только косвенное. Администраторы сайтов время от времени посматривают на хиты и хосты, радуются, когда подобные показатели возрастают, и удивляются, – когда снижаются.
Однако сегодня Интернет-статистика – очень мощный инструмент, который при правильном использовании сможет помогать Вашему бизнесу. Недаром многие иностранные фирмы, предоставляющие подобные сервисы, гордо называют их «EBusiness Intelligence Products».
В Рунете с Интернет-статистикой сложилось довольно-таки странная картина (прежде всего, это относится к коммерческим проектам, корпоративным сайтам). Одни при слове «статистика» недоуменно пожимают плечами. Другие утверждают, что, кроме счетчика HotLog, им ничего и не надо. Третьи заказывают дорогие статистические online-системы только для внутреннего использования, просматривают графики и отчеты, не делая при этом никаких существенных выводов. Некоторые же используют статистические отчеты для того, чтобы понять, что еще можно улучшить в предоставляемых сервисах, переносят опыт в offline, анализируют эффективность маркетинговых акций.
2. Инструменты сбора статистики
Счетчики. Пожалуй, самый известный и популярный в настоящее время способ получить сведения о посетителях Интернет-ресурса. Количество подобных счетчиков (порою объединенных с рейтингами) исчисляется десятками. Среди них можно выделить несколько лидеров: HotLog, SpyLOG, Liveinternet, Rating@Mail.ru, Rambler’s Top100 и некоторые другие.
Нестандартные счетчики. Существует ряд систем, которые пытаются интерпретировать статистические данные не совсем обычным способом. Среди таких систем – Netvertising и IntelliMetr. Специфика первой в том, что она объединяет данные, полученные от счетчиков, с данными анкет, регистраций и т.п. Специфика второй – в бизнес-подходе: сервис предоставляет информацию о продажах, регистрациях, эффективности работы партнеров – обо всем, что интересует маркетологов.
Анализаторы log-файлов. Принцип работы этих систем – в анализе стандартной информации, накапливаемой в файлах журнала любого веб-сервера. Наиболее популярным бесплатным анализатором является Analog.
Собственная система статистики. Для большинства коммерческих проектов подобная система является оптимальным вариантом. Это – не самое дешевое решение, но позволяющее реализовать практически все ваши мысли и пожелания. Однако для создания подобной системы потребуется немалый опыт, а также довольно длительный период для устранения ошибок и недочетов созданной системы.
Более подробную информацию об Интернет-статистике можно найти на сайте Oborot.rU.
3. Скрипт для сбора статистики из log-файлов
Итак, мы рассмотрели основные инструменты для сбора статистики в Интернете. Со счетчиками все просто: зашли на интересуемый сайт, предоставляющий подобный сервис, зарегистрировались и можно «пользоваться».
С программами-анализаторами немного сложнее: если на приобретение программного обеспечения требуется сравнительно малое время и небольшие затраты, то для освоения потребуется достаточно длительное время (а порою и дополнительные затраты).
Создание же собственной системы статистики для многих – совершенно неприемлемый вариант: существенные временные и материальные затраты на реализацию подобного проекта могут совершенно не окупиться, поэтому позволить подобное могут лишь большие корпоративные сайты.
Что же делать маленьким и беззащитным, но гордым и принципиальным? Можно попробовать создать собственную небольшую систему статистики – своеобразный гибрид программы-анализатора и счетчика. Подобную систему всегда будет просто подстроить под себя, постоянно совершенствуя и дополняя ее новыми возможностями.
Для решения поставленной задачи напишем скрипт, позволяющий собирать статистику из log-файлов произвольного веб-ресурса.
Сразу стоит сказать, что форматы log-файлов на различных сайтах зачастую отличаются друг от друга. Поэтому для использования приведенного ниже скрипта в собственных целях необходима его достаточно простая корректировка (регулярного выражения, интересуемых User-Agent и т.д.).
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Сбор статистики из log-файлов</title>
<meta http-equiv="content-type" content="text/html; charset=windows-1251">
<meta http-equiv="content-language" content="ru">
</head>
<style>
* {
font-family: Arial, Helvetica, sans-serif;
font-size: 12px;
}
</style>
<script language="javascript">
function ip_st(state)
{
if (document.all)
{
document.all.ip.disabled = state;
document.all.req_ip.disabled = state;
}
else
if (document.getElementById) // Для Netscape/Mozilla
{
document.getElementById('ip').disabled = state;
document.getElementById('req_ip').disabled = state;
}
}
function cd_st(state)
{
if (document.all)
{
document.all.code.disabled = state;
document.all.req_code.disabled = state;
}
else
if (document.getElementById) // Для Netscape/Mozilla
{
document.getElementById('code').disabled = state;
document.getElementById('req_code').disabled = state;
}
}
function ua_st(state)
{
if (document.all)
{
document.all.user_agent.disabled = state;
document.all.req_user_agent.disabled = state;
}
else
if (document.getElementById) // Для Netscape/Mozilla
{
document.getElementById('user_agent').disabled = state;
document.getElementById('req_user_agent').disabled = state;
}
}
</script>
<body>
<formaction="la.php?action=exec" method="post">
<font style="font-weight: bold;">Введите URI интересующего log-файла:</font><br>
<input style="width: 300px;" type="text" name="uri" value="<? if ($uri) { echo $uri; } else { echo "http://www.domain.ru/access.log"; } ?>">
<br>
<br>
<font style="font-weight: bold;">Выберите отображаемые поля:</font>
<br><input name="chckbx[1]" type="checkbox" <?if ($chckbx[1]) { echo "checked"; } else { echo "unchecked"; }?>>Имя домена
<br><input name="chckbx[2]" type="checkbox" <?if ($chckbx[2]) { echo "checked"; } else { echo "unchecked"; }?>>IP
<br><input name="chckbx[3]" type="checkbox" <?if ($chckbx[3]) { echo "checked"; } else { echo "unchecked"; }?>>Дата
<br><input name="chckbx[4]" type="checkbox" <?if ($chckbx[4]) { echo "checked"; } else { echo "unchecked"; }?>>Время
<br><input name="chckbx[5]" type="checkbox" <?if ($chckbx[5]) { echo "checked"; } else { echo "unchecked"; }?>>Запрос
<br><input name="chckbx[6]" type="checkbox" <?if ($chckbx[6]) { echo "checked"; } else { echo "unchecked"; }?>>Код ответа
<br><input name="chckbx[7]" type="checkbox" <?if ($chckbx[7]) { echo "checked"; } else { echo "unchecked"; }?>>Размер запрашиваемой страницы
<br><input name="chckbx[8]" type="checkbox" <?if ($chckbx[8]) { echo "checked"; } else { echo "unchecked"; }?>>URI домена
<br><input name="chckbx[9]" type="checkbox" <?if ($chckbx[9]) { echo "checked"; } else { echo "unchecked"; }?>>User-Agent
<br>
<br>
<font style="font-weight: bold;">Используемые фильтры:</font>
<br><input name="chckbx_ip" type="checkbox" <?if ($chckbx_ip) { echo "checked"; } else { echo "unchecked"; }?> onclick="if (document.forms[0].chckbx_ip.checked) { ip_st(false); } else { ip_st(true); }">IP
<br>
<select style="width: 300px;" name="ip" id="ip" selected="<? echo $ip; ?>" <?if ($chckbx_ip) { echo ""; } else { echo "disabled"; }?>>
<option value="87.250.231.14" <? if ($ip == "87.250.231.14") { echo "selected"; } ?>>87.250.231.14</option>
<option value="213.180.207.25" <? if ($ip == "213.180.207.25") { echo "selected"; } ?>>213.180.207.25</option>
</select>
<br>(используется, если поле ниже пустое)
<br>
<input style="width: 300px;" type="text" name="req_ip" id="req_ip" value="<? if ($req_ip) { echo $req_ip; } else { echo ""; } ?>" <?if ($chckbx_ip) { echo ""; } else { echo "disabled"; }?>>
<br><input name="chckbx_cd" type="checkbox" <?if ($chckbx_cd) { echo "checked"; } else { echo "unchecked"; }?> onclick="if (document.forms[0].chckbx_cd.checked) { cd_st(false); } else { cd_st(true); }">Код ответа
<br>
<select style="width: 300px;" name="code" id="code" selected="<? echo $code; ?>" <?if ($chckbx_cd) { echo ""; } else { echo "disabled"; }?>>
<option value="200" <? if ($code == "200") { echo "selected"; } ?>>200 - Ok</option>
<option value="304" <? if ($code == "304") { echo "selected"; } ?>>304 - Not Modified</option>
<option value="403" <? if ($code == "403") { echo "selected"; } ?>>403 - Forbidden</option>
<option value="404" <? if ($code == "404") { echo "selected"; } ?>>404 - Not Found</option>
</select>
<br>(используется, если поле ниже пустое)
<br>
<input style="width: 300px;" type="text" name="req_code" id="req_code" value="<? if ($req_code) { echo $req_code; } else { echo ""; } ?>" <?if ($chckbx_cd) { echo ""; } else { echo "disabled"; }?>>
<br><input name="chckbx_ua" type="checkbox" <?if ($chckbx_ua) { echo "checked"; } else { echo "unchecked"; }?> onclick="if (document.forms[0].chckbx_ua.checked) { ua_st(false); } else { ua_st(true); }">User-Agent
<br>
<select style="width: 300px;" name="user_agent" id="user_agent" selected="<? echo $user_agent; ?>" <?if ($chckbx_ua) { echo ""; } else { echo "disabled"; }?>>
<option value="Yandex/1.01.001 (compatible; Win16; I)" <? if ($user_agent == "Yandex/1.01.001 (compatible; Win16; I)") { echo "selected"; } ?>>Yandex/1.01.001 (compatible; Win16; I)</option>
<option value="Yandex/1.01.001 (compatible; Win16; P)" <? if ($user_agent == "Yandex/1.01.001 (compatible; Win16; P)") { echo "selected"; } ?>>Yandex/1.01.001 (compatible; Win16; P)</option>
<option value="Yandex/1.01.001 (compatible; Win16; H)" <? if ($user_agent == "Yandex/1.01.001 (compatible; Win16; H)") { echo "selected"; } ?>>Yandex/1.01.001 (compatible; Win16; H)</option>
<option value="Yandex/1.02.000 (compatible; Win16; F)" <? if ($user_agent == "Yandex/1.02.000 (compatible; Win16; I)") { echo "selected"; } ?>>Yandex/1.02.000 (compatible; Win16; F)</option>
<option value="Yandex/1.03.003 (compatible; Win16; D)" <? if ($user_agent == "Yandex/1.03.003 (compatible; Win16; D)") { echo "selected"; } ?>>Yandex/1.03.003 (compatible; Win16; D)</option>
<option value="Yandex/1.03.000 (compatible; Win16; M)" <? if ($user_agent == "Yandex/1.03.000 (compatible; Win16; M)") { echo "selected"; } ?>>Yandex/1.03.000 (compatible; Win16; M)</option>
</select>
<br>(используется, если поле ниже пустое)
<br>
<input style="width: 300px;" type="text" name="req_user_agent" id="req_user_agent" value="<? if ($req_user_agent) { echo $req_user_agent; } else { echo ""; } ?>" <?if ($chckbx_ua) { echo ""; } else { echo "disabled"; }?>>
<br>
<br>
<input style="width: 300px;" type="submit" name="exec" value="Собрать статистику">
</form>
<?
if ($action == exec)
{
// Указываем номер порта соединения (при необходимости изменить)
$httpport = 80;
// Удаляем "http://", если URI содержит данную подстроку
$uri = (substr(trim($uri), 0, 7) == "http://") ? substr(trim($uri), 7) : $uri;
// Выделяем из URI домен и страницу (если она присутствует):
// $res[1] будет содержать имя домена (заканчиваться должен слэшем)
// $res[2] будет содержать имя страницы (без имени домена)
preg_match("/(w{0,3}\.?[\w\W]+\.\w{2,3})(?=\/)\/([\w\W]*)\/?/", $uri, $res);
// Открывает сокет соединения указанного домена/страницы
$fp = @fsockopen($res[1], $httpport);
// Сообщаем об ошибке, в случае если соединение не было установлено
// Возможно по причине долгого ответа сервера или неверного URI
if (!$fp)
{
echo "<font color=\"#FF0000\">";
echo "Невозможно установить соединение!";
echo "</font></body></html>";
exit;
}
// Формируем запрос для указанного домена
$query = "GET /".$res[2]." HTTP/1.1\r\n";
$query = $query."HOST: ".$res[1]."\r\n";
$query = $query."Connection: close\r\n\r\n";
// Отправляем домену запрос
fputs($fp, $query);
while (!feof($fp))
{
// Получаем ответ от домена (по одной строке)
$str .= fgets($fp);
}
// Закрываем соединение
fclose($fp);
// Выбираем из ответа сервера нужные нам части
preg_match_all("/(.*)\s+(\d{2,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*\[(.*?)\:(.*?)\s+\+\d{4}\]\s+\"(.*?)\"\s+(\d{1,})\s+(\d{1,}\-)\s+\"(.*?)\"\s+\"(.*?)\"/i", $str, $res);
//
^ ^ Наличие "?" обязательно, иначе жадный паттерн ".*" заберет слишком "много"
echo "Общее количество записей равно ".sizeof($res[1])."<br><br>\n\n";
$str = "";
$num = "";
$ptr = "";
$str .= "<table border=\"1\">\n\n";
$str .= "<tr>\n";
// Заголовок таблицы
if ($chckbx[1])
$str .= "<td style=\"font-weight: bold;\">Имя домена</td>\n";
if ($chckbx[2])
$str .= "<td style=\"font-weight: bold;\">IP</td>\n";
if ($chckbx[3])
$str .= "<td style=\"font-weight: bold;\">Дата</td>\n";
if ($chckbx[4])
$str .= "<td style=\"font-weight: bold;\">Время</td>\n";
if ($chckbx[5])
$str .= "<td style=\"font-weight: bold;\">Запрос</td>\n";
if ($chckbx[6])
$str .= "<td style=\"font-weight: bold;\">Код ответа</td>\n";
if ($chckbx[7])
$str .= "<td style=\"font-weight: bold;\">Размер запрашиваемой страницы</td>\n";
if ($chckbx[8])
$str .= "<td style=\"font-weight: bold;\">URI домена</td>\n";
if ($chckbx[9])
$str .= "<td style=\"font-weight: bold;\">User-Agent</td>\n";
$str .= "</tr>\n\n";
if ($req_ip != "")
$ip = $req_ip; // В случае, если поле не пустое
if ($req_code != "")
$code = $req_code; // В случае, если поле не пустое
if ($req_user_agent != "")
$user_agent = $req_user_agent; // В случае, если поле не пустое
// sizeof($res[1]) - общее количество найденных групп совпадений
for ($j = 0; $j < sizeof($res[1]); $j++)
{
// sizeof($res) - количество совпадений в группе
for ($i = 1; $i < sizeof($res); $i++)
{
// Проверяем совпадения и отмечены ли соответствующие поля
if (($res[2][$j] == $ip $chckbx_ip != "on") && ($res[6][$j] == $code $chckbx_cd != "on") && ($res[9][$j] == $user_agent $chckbx_ua != "on") && $chckbx[$i] == "on")
{
if ($ptr != "1")
{
$str .= "<tr>\n";
$ptr = "1";
}
$str .= "<td>".$res[$i][$j]."</td>\n";
$num = "1";
}
else
{
continue;
}
}
if ($ptr == "1")
{
$str .= "</tr>\n\n";
$ptr = "";
}
}
$str .= "</table>\n\n";
if ($num == "1") // Если нашли хотя бы одно совпадение...
echo $str;
else// ...иначе - сообщение об ошибке!
echo "<fontcolor=\"#FF0000\">Нет записей, удовлетворяющих запросу!</font>\n\n";
}
Чтобы проверить работу данного скрипта, можно использовать два небольших (но реальных) log-файла, приведенных ниже:
Файл access_log.1
minchange1.your-inet.ru 213.180.217.222 - - [17/Dec/2006:06:37:06 +0300] "GET / HTTP/1.1" 200 4325 "-" "Yandex/1.01.001 (compatible; Win16; H)"
minchange1.your-inet.ru 213.180.217.222 - - [17/Dec/2006:06:37:06 +0300] "GET /robots.txt HTTP/1.1" 404 300 "-" "Yandex/1.01.001 (compatible; Win16; H)"
minchange1.your-inet.ru 213.180.217.222 - - [18/Dec/2006:22:16:04 +0300] "GET / HTTP/1.1" 200 4325 "-" "Yandex/1.01.001 (compatible; Win16; H)"
minchange1.your-inet.ru 213.180.217.222 - - [18/Dec/2006:22:16:04 +0300] "GET /robots.txt HTTP/1.1" 404 300 "-" "Yandex/1.01.001 (compatible; Win16; H)"
minchange1.your-inet.ru 80.78.192.108 - - [20/Dec/2006:14:45:33 +0300] "GET / HTTP/1.0" 200 4325 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.1) Gecko/20061010 Firefox/2.0"
minchange1.your-inet.ru 80.78.192.108 - - [20/Dec/2006:14:45:41 +0300] "GET /rd.php HTTP/1.0" 200 688 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.1) Gecko/20061010 Firefox/2.0"
minchange1.your-inet.ru 80.78.192.108 - - [20/Dec/2006:14:45:50 +0300] "POST /rd.php?action=exec HTTP/1.0" 200 3961 "http://minchange1.your-inet.ru/rd.php" "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.1) Gecko/20061010 Firefox/2.0"
Файл access_log.2
minchange4.your-inet.ru 213.180.206.10 - - [26/Nov/2006:23:31:57 +0300] "GET /robots.txt HTTP/1.1" 404 300 "-" "Yandex/1.01.001 (compatible; Win16; I)"
minchange4.your-inet.ru 213.180.206.10 - - [26/Nov/2006:23:31:58 +0300] "GET / HTTP/1.1" 200 3585 "-" "Yandex/1.01.001 (compatible; Win16; I)"
minchange4.your-inet.ru 80.78.192.108 - - [28/Nov/2006:17:39:37 +0300] "GET / HTTP/1.0" 200 3638 "-" "Opera/9.00 (Windows NT 5.1; U; ru)"
minchange4.your-inet.ru 80.78.192.108 - - [28/Nov/2006:17:39:38 +0300] "GET /favicon.ico HTTP/1.0" 404 301 "http://minchange4.your-inet.ru/" "Opera/9.00 (Windows NT 5.1; U; ru)"
В заключение отметим, что подобный скрипт будет полезен как начинающим, так и уже «состоявшимся» SEO-оптимизаторам. С его помощью можно, например, следить за «похождениями» любого робота-индексатора (не только Яндекса, который здесь выбран лишь для примера) – как часто посещает сайт, какие страницы смотрит и т.д.; вести статистику посещений (но при некоторых доработках).
С течением времени при определенном опыте и желании на основе этой статистике можно будет построить свою собственную базу данных, что вкупе уже будет представлять сравнительно крупную систему статистики вашего собственного сайта. Все это в последующем при правильном использовании будет положительно сказываться на трафике и рейтинге Интернет-ресурса.









Сайт работает на системе
Техническая реализация: