Nickolay.info. PHP. Самые популярные запросы к сайту

Готового бесплатного скрипта не нашел, пришлось писать свой.

Итак, мы хотим определять, с какими запросами обращались пользователи к нашим динамически формируемым страницам на PHP. Технически ничего сложного в задаче нет - в PHP имеется глобальная переменная $HTTP_REFERER для обращения к соответствующему свойству протокола HTTP. Это свойство содержит URL-адрес источника запроса к странице. Так, если Вы перешли в браузере по ссылке с одной страницы на другую, свойство Referer будет содержать адрес первой страницы. Обратиться к Referer можно двумя способами:

global $HTTP_REFERER;
header("Location: $HTTP_REFERER");
- здесь мы перенаправляем запрос обратно на вызывающую страницу. Для надежности глобальная переменная PHP объявлена в явном виде. Такой подход потребует включения настройки register_globals = On из файла c:\Winodws\php.ini, что считается устаревшим и не очень надежным методом.
$http_referer="/";
if (isset($_SERVER['HTTP_REFERER'])) {
 $http_referer=$_SERVER['HTTP_REFERER'];
}
- а здесь мы читаем значение переменной из массива $_SERVER, определенного в PHP. Это более современный и безопасный подход.

При переходе на страницу с поисковика, referer, как правило, содержит не только адрес поисковика, но и сам запрос, переданный ему методом GET (то есть, через адресную строку браузера). Проблема в том, что у каждого поисковика могут быть свои правила обработки запросов и формирования URL-адресов. Поэтому не остается ничего другого, как изучить формат адресной строки популярных поисковых машин. Для простоты, а также для того, чтоб не лазить каждый раз в базу данных, у меня строки описания поисковиков хранятся в обычном текстовом файле data.txt. Вот его распечатка:

# В этом файле допустимо любое число пробелов между словами. 
# Но все строки не содержат пробелов внутри отдельных слов!
# После # строка не читается (комментарий)
#
# Описание одной записи о поисковой машине:
#  
#  Номер поисковика в базе - существующие менять нельзя!
#  Имя переменной с текстом в строке запроса - без $ в началe!
#  Название поисковика для отображения
#  Строка для идентификации поисковика - лучше начинать с /домен, 
#    варианты перехода с www. в адресе и без него учтены в коде
#  Строка, после которой идут параметры запроса
#  Надо ли декодировать из UTF-8 в Win (1/0) 
#    или как перекодировать через convert_cyr_string 
#    (см. в описании этой функции PHP, например, kw - из KOI-8 в Windows)
#
0  text  Яndex     /www.yandex.ru       /yandsearch   1 #Первая страница выдачи Яndex
0  text  Яndex     /www.yandex.ru       /yandpage     1 #Другие страницы
1  words Rambler   /www.rambler.ru      /srch         0
1  query Rambler   /nova.rambler.ru     /srch         1
2  q     Mail.Ru   /go.mail.ru          /search       0
3  q     Google    /www.google.         /search       1
4  p     Yahoo     /ru.search.yahoo.com /search       1
5  r     Апорт     /sm.aport.ru         /scripts      1
6  q     AllTheWeb /www.alltheweb.com   /search       1
7  q     AltaVista /www.altavista.com   /results      1
# Добавлять записи можно строкой выше, номер каждого поисковика д.б. уникален
# В конце не надо лишних пустых строк

- как видите, у одного поисковика может быть несколько форматов запроса, поэтому об одной машине может быть несколько записей с совпадающим номером. Кроме того, многие поисковики кодируют Ваш запрос в международную кодировку UTF-8, этот факт отражает последний столбец.

Всё остальное - дело техники. На PHP нетрудно написать функцию, которая будет анализировать строку referer на предмет наличия в ней частей URL-адреса известных поисковиков, выделять и декодировать строку запроса, а затем добавлять ее в базу данных. Если Вам хочется добавить в список новый поисковик, Вы не только можете сделать это, но еще и сообщить мне, я добавлю его в "официальную" сборку скрипта.

Установка и настройки

Немного о настройках и порядке установки. Очевидно, что этот скрипт Вы будете встраивать в имеющийся движок, ведь в качестве отдельного приложения он бесполезен. Поэтому в архиве всё, что нужно только для демонстрации, убрано в папку design (при этом можно на локалхосте запустить index.php и поэкспериментировать с закомментаренными там примерами реальных referer). А без этой папки сделать остается совсем немного:

  1. Добавить в базу данных движка 2 таблицы со следующей структурой:
    CREATE TABLE search_queries (  #Информация о поисковых запросах
     text varchar(255),  #Текст запроса
     counter bigint,     #Число обращений с этим запросом
     dtime bigint        #Дата/время последнего запроса
    );
    
    CREATE TABLE search_machines ( #Информация о поисковых машинах
     text varchar(255),  #Название поисковика
     counter bigint,     #Число переходов с этого поисковика
     dtime bigint        #Дата/время последнего перехода
    );
    
    (запрос лежит в файле !sql/create_table.sql).
  2. Закинуть файлы functions.php, db.php и data.txt в папку сервера, где лежат файлы PHP-движка. Если это корневая папка, достаточно из нужного места в коде добавить вызов двух функций:
     require_once ("functions.php");
     $http_referer = get_http_referrer ();
     get_referrer_query ($http_referer,10,'; ');
    
    - последняя функция еще и вернет текст запроса, с которым обратились к странице (либо пустую строку, если запрос не найден). Ее второй параметр задаёт число выводимых записей (сортируются по уменьшению числа запросов), а третий - разделитель между записями.

    Если удобнее положить файлы в отдельную вложенную папку (например, с именем referer), придется немного поменять код:

     require_once ("referer/functions.php");
     $http_referer = get_http_referrer ();
     get_referrer_query ($http_referer,10,'; ');
    
    - и тогда в коде модуля functions.php:
    require_once ("referer/db.php");
    ...
    $temp = parseStrings(readData ('referer/data.txt'));

    - дело в том, что включение файла с путем к папке (referer/functions.php) не заставит интерпретатор PHP рассматривать пути к новым включениям из functions.php как начинающиеся с папки referer. Других изменений, как будто, не потребуется.

  3. В коде модуля db.php прописать подключение к базе:
     function dbconnect() {
      $mysql=mysql_pconnect("localhost", "root", "root"); //хост, логин, пароль
      mysql_select_db("bbpost"); //имя базы данных
      ...
    
    У Вас может быть собственный модель, исполняющий те же функции, тогда лучше пользоваться им. Кроме того, на ряде хостингов проблемно работает функция mysql_pconnect - тогда ставим вместо нее имя mysql_connect.

Направления развития скрипта

Разумеется, можно сделать лучше, чем в этой бесплатной демке (правда, тогда и запросов к базе станет больше).

  1. Между запросами и поисковиками напрашивается соотношение "многие ко многим", то есть, один запрос может делаться с разных поисковиков и наоборот, с одного поисковика могут ходить с разными запросами. Добавив в запрос код вида
    CREATE TABLE search_statistics (  #Связь поисковиков и запросов
     qid bigint,
     mid bigint,
     counter bigint,      #Число обращений с этим запросом
     dtime bigint         #Дата/время последнего запроса
    );
    
    мы создадим третью таблицу для связи. Правда, тогда в search_queries и search_machines придется добавить поля-счетчики вида
    id int PRIMARY KEY auto_increment,
    
    да еще и заставить функцию update_table возвращать id полученной или добавленной записи:
     function update_table ($table, $text) { //Обновить данные таблицы search_queries или search_machines
      $sql = "select * from $table where text='".$text."' limit 0,1";
      $result = dbquery($sql) or die (mysql_error());
      if ($result and dbrows($result)) { //Уже есть запись
       $note = dbfetcha($result);
       $c1 = $note['counter']+1;
       $sql="update $table set counter='$c1', dtime='".time()."' where text='".$text."'";
       $result = dbquery($sql) or die (mysql_error());
      }
      else { //Новая запись
       $sql="insert into $table (text,counter,dtime) values ('$text', '1', '".time()."')";
       $result = dbquery($sql) or die (mysql_error());
       //Лишний запрос, чтоб узнать id только что добавленной записи
       $sql = "select id from $table where text='".$text."' limit 0,1";  
       $result = dbquery($sql) or die (mysql_error());
       $note = dbfetcha($result);  
      }
      return $note['id'];
     }  
    
     function update_link ($qid,$mid) {
      $sql = "select * from search_statistics where qid='".$qid."' and mid='".$mid."' limit 0,1";  
      $result = dbquery($sql) or die (mysql_error());
      if ($result and dbrows($result)) {
       $note = dbfetcha($result);
       $c1 = $note['counter']+1;
       $sql="update search_statistics set counter='$c1', dtime='".time()."' where qid='".$qid."' and mid='".$mid."'";
       $result = dbquery($sql) or die (mysql_error());
      }
      else {
       $sql="insert into search_statistics (qid,mid,counter,dtime) values ('$qid', '$mid', '1', '".time()."')";
       $result = dbquery($sql) or die (mysql_error());
      }
     }
    
     ...
     $qid=update_table ('search_queries', $query_value);
     $mid=update_table ('search_machines',$machine_name);
     update_link ($qid,$mid); //Проверить и обновить связь между таблицами
    
    Тогда можно и учесть, с каких именно поисковиков с какими именно запросами приходили.
  2. Если сохранять в базе идентификатор текущий страницы (обычно это параметр, переданный скрипту методом POST или GET), можно накапливать стастистику и по отдельным страницам сайта.
  3. Нужна админка, чтобы всё это чистить и исправлять.

Скачать и демо

Скрипт работает, например, здесь

Скачать: userqueries.zip (15 Кб)

Рейтинг@Mail.ru
вверх гостевая; E-mail