• XSS.stack #1 – первый литературный журнал от юзеров форума

Парсер REFERER'ов с поисковых систем

DeusTirael

(L1) cache
Забанен
Регистрация
04.01.2006
Сообщения
525
Реакции
3
Пожалуйста, обратите внимание, что пользователь заблокирован
Парсер REFERER'ов с поисковых систем
04.02.2009 | Категория: Web-мастеру и не только | Автор: ManHunter
Оригинал: http://www.manhunter.ru/webmaster/73_parse...vih_sistem.html

Обработка заголовка HTTP referer является одной из важных задач при раскрутке сайта и сборе статистики. По нему можно определить, какие ресурсы ссылаются на ваш сайт. Но особую ценность представляют данные посещений с поисковых систем, так как эта информация позволяет наиболее четко определить, по каким ключевым словам ваш сайт может быть найден, а также проанализировать эффективность поисковой оптимизации вашего ресурса. Если вы пользуетесь сторонними счетчиками посещений, то эту информацию они обычно предоставляют сами. В некоторых случаях такие данные предоставляют серверные системы статистики типа Webalizer. Я принципиально не пользуюсь ни тем, ни другим, обрабатываю все данные самостоятельно. Для этого была написана функция обработки рефереров, которую я использую в своих проектах. Данные поискового запроса обычно передаются методом GET и содержатся в строке браузера, но основная проблема в том, что кодировка этих данных может быть разной даже в пределах одной и той же поисковой системы. Как выяснилось, не везде доступна штатная функция PHP is_unicode(), поэтому для подстраховки пришлось написать свою. Проверка выполняется согласно правилам формирования Юникода.

Код:
// Функция проверки является ли переменная строкой в Юникоде  
// Если штатная функция не определена, то применить нашу 
if (!function_exists('is_unicode')) { 
  function is_unicode($str) { 
    for ($i=0; $i<strlen($str); $i++) { 
      // Если символ с кодом больше 191, то возможно это юникод 
      if (ord($str[$i])>191) { 
        // Следующий символ должен быть в интервале 
        // 10000000b ... 10111111b (128...191) 
        if (ord($str[($i+1)])<128 || ord($str[($i+1)])>191) { 
          // Условие не выполнено, значит это не юникод 
          return false; 
        } 
        else { 
          // Пропускаем один байт, т.к. он является частью символа 
          $i++; 
        } 
      } 
    } 
    // Проверка пройдена, это юникод 
    return true; 
  } 
}

Теперь, когда мы можем четко определить кодировку строки запроса, нам необходимо выделить ее из строки URL. Для этого достаточно выполнить в интересуемом поисковике любой запрос и посмотреть как формируется ссылка.

Если сервер настроен правильно, то поле реферера обычно доступно в переменных окружения через функцию getenv() или через суперглобальные массивы $_ENV и $_SERVER. Готовая функция разбора реферера у меня получилась следующей:

Код:
// Функция разбора поля REFERER 
function parse_refer($refer) { 
  // База данных поисковых систем 
  $search_engines=Array( 
    Array("name"=>"Картинки.Mail", "pattern"=>"go.mail.ru/search_images", "param"=>"q="), 
    Array("name"=>"Mail", "pattern"=>"go.mail.ru", "param"=>"q="), 
    Array("name"=>"Google Images", "pattern"=>"images.google.", "param"=>"q="), 
    Array("name"=>"Google", "pattern"=>"google.", "param"=>"q="), 
    Array("name"=>"Google", "pattern"=>"google.", "param"=>"as_q="), 
    Array("name"=>"Live Search", "pattern"=>"search.live.com", "param"=>"q="), 
    Array("name"=>"RapidShare Search Engine", "pattern"=>"rapidshare-search-engine", "param"=>"s="), 
    Array("name"=>"Rambler", "pattern"=>"rambler.ru", "param"=>"query="), 
    Array("name"=>"Rambler", "pattern"=>"rambler.ru", "param"=>"words="), 
    Array("name"=>"Yahoo!", "pattern"=>"search.yahoo.com", "param"=>"p="), 
    Array("name"=>"Nigma", "pattern"=>"nigma.ru/index.php", "param"=>"s="), 
    Array("name"=>"Nigma", "pattern"=>"nigma.ru/index.php", "param"=>"q="), 
    Array("name"=>"MSN", "pattern"=>"search.msn.com/results", "param"=>"q="), 
    Array("name"=>"Ask", "pattern"=>"ask.com/web", "param"=>"q="), 
    Array("name"=>"QIP", "pattern"=>"search.qip.ru/search", "param"=>"query="), 
    Array("name"=>"RapidAll", "pattern"=>"rapidall.com/search.php", "param"=>"query="), 
    Array("name"=>"Яндекс.Картинки", "pattern"=>"images.yandex.ru/", "param"=>"text="), 
    Array("name"=>"Яндекс.Mobile", "pattern"=>"m.yandex.ru/search", "param"=>"query="), 
    Array("name"=>"Яндекс", "pattern"=>"hghltd.yandex.net", "param"=>"text="), 
    Array("name"=>"Яндекс", "pattern"=>"yandex.ru", "param"=>"text=") 
  ); 
  
  // Отрезать от ссылки "хвост" 
  $tmp=explode("?",$refer); 
  $chk_site=$tmp[0];  // Имя сайта 
  // Разобрать "хвост" на отдельные параметры 
  $params=split("&",implode("&",$tmp)); 
  
  $result_engine=""; 
  $result_title=$refer; 
  for ($i=0; $i<count($params); $i++) { 
    // Параметр пустой, пропустить 
    if ($params[$i]=="") { continue; } 
    foreach ($search_engines as $engine) { 
      // Поиск по всем сигнатурам 
      if (strpos($chk_site,$engine['pattern']) && substr($params[$i],0,strlen($engine['param']))==$engine['param']) { 
        // Сигнатура найдена 
        $result_title=substr($params[$i],strlen($engine['param'])); 
        $result_engine=$engine['name']; 
        break; 
      } 
    } 
  } 
  
  if ($result_engine!="") { 
    // Привести строку в текстовый вид 
    $str=trim(urldecode($result_title)); 
    // Если строка в юникоде, то перевести ее в кодировку win1251 
    if (is_unicode($str)) { 
      $str=iconv("utf-8","windows-1251",$str); 
    } 
    if ($str!="") { 
      // Сформировать строку "Имя поисковой системы: запрос" 
      $result=$result_engine.": ".$str; 
    } 
    // Пустой поисковый запрос 
    else { 
      $result=""; 
    } 
  } 
  else { 
    $result=""; 
  } 
  return $result; 
}

На выходе получаем строку типа "Google: парсер ссылки на php" в кодировке win1251, или пустую строку, если реферер разобрать и опознать не удалось. Пример использования:

Код:
$refer=trim(getenv('HTTP_REFERER')); 
$engine=parse_refer($refer); 
// Дальше выполняются какие-то действия, например запись в базу

Базу поисковиков, известных функции, можно легко пополнять по уже имеющимся образцам. Параметр name - название поисковой системы, pattern - сигнатура, которая однозначно должна присутствовать в имени домена поисковика и param - сигнатура строки, после которой начинается текст поискового запроса. При использовании функции не забывайте проверять, чтобы в обработку не попадали внутрисайтовые рефереры.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх