PHP

Парсинг Алексы (parsing xml Alexa.com)

Частенько в сети можно найти различные способы парсинга сайта Alexa.com. В любых случаях суть парсинга сводится к тому, чтобы вытянуть данные какого-либо сайта и разложить их "по полочкам" для удобного вывода на экран пользователю. Вытягивать данные можно например, php-функцией file_get_contents(), обычно нубы (новички) делают именно так:
$v = file_get_contents($l);

либо используя самописную (пользовательскую) функцию (ее пример ниже):
$v = load_content($l,2);

а можно вытянуть не html-страницу, а xml-данные, в которых уже все переменные готовы и их нужно только вытащить на экран, используя DOM. Для удобства дальнейшей обработки переменных, можно их присвоить другим переменным.

Но это еще не все. На сайте Алексы есть несколько вариантов xml-файлов, о чем я случайно недавно узнал методом научного тыка, в сети нигде никаких упоминаний об этом не встречал, вот и решил поделиться своими сетевыми заметками.

Итак, вариант парсинга сайта Alexa.com чаще всего можно встретить с вытягиванием html-страницы, например так:
<?php
  $url = 'isle-blog.ru';
  $link = 'http://alexa.com/siteinfo/'.$url;
  $data = file_get_contents($link);
  //echo htmlspecialchars($data); - выводим наши данные для проверки.
  //<div class="data up"><img src="/images/icons/globe-sm.jpg" alt="Global" style="margin-bottom:-2px;"/> 1000</a></div>
  preg_match('|<div class="data up"><img[^\>]*>\s*(.*?)\s*(?:</a>)?</div>|', $data, $rank);
  ...
  $alex_rank = $rank[1] ? $rank[1] : 'n/a';
?>

На сайте Алексы есть местами корявый код с ошибками, ввидимо, и там криворукие программеры сидят, как и на этом хостинге оперы... поэтому, сделаем маленькую хитрость на тот случай, если ошибку все-таки исправят, вот так:
\s*(?:</a>)?

в строке с кодом:
</a></div>

вариант аналогичный, с вытягиванием xml-данных: Либо можно вытащить данные через php-библиотеку C_URL:
<?php
  $agent = 'Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5';
  $timeout = 8;
  $err = 'Error open site '.$site_domain.', try again later. ';

  $ch = curl_init($url);
  curl_setopt($ch,CURLOPT_USERAGENT, $agent);

?>

Использовать php-библиотеку C_URL нет особого смысла, можно обойтись более простым способом - функцией file_get_contents(), но (не в данном случае) некоторые сайты, например, Технорати (technorati.com) не позволяют тырить свой контент, поэтому, данные с них можно вытягивать только через php-библиотеку C_URL, используя такие хитрости, как имитацию браузера, передавая ресурсу Юзер_Агент, он может выглядеть, например, так:
$agent = 'Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5';
Еще php-библиотека C_URL удобна тем, что может выдерживать паузы, перед тем, как закрыть соединение с сайтом. Например, если в течении пяти секунд данные не были получены, то конечный результат сразу же можно сделать нулевым, не выполняя никакие его обработки для вывода на экран - бывает удобным. Хотя, паузы, а также получение заголовка сайта (ответ сервера) можно сделать и не прибегая к Курлам. Отличительной чертой Курлов считаю в основном то, что можно разрешить переход по редиректу или запретить, удобно если сайт берем как site.ru, a урл редиректит как www.site.ru. Также удобно и то, что можно получить этот самый редирект - удобно, когда набераешь site.ru, а адрес редиректит на site2.ru.
<?php
  $url = 'isle-blog.ru';
  $link = 'http://data.alexa.com/data?cli=10&dat=snba&url='.$url;
  $data = file_get_contents($link);
  //print_r($data); - выводим наши данные для проверки.
  //<POPULARITY URL="isle-blog.ru/" TEXT="1000"/>
  preg_match('|<POPULARITY URL="[^\"]*" TEXT="([^\"]*)"/>|',$data,$rank);
  ...
  $alex_rank = $rank[1] ? $rank[1] : 'n/a';
?>

Обращаю внимание, что вывод простой html-страницы можно осуществить коммандой "эхо" (отражение): echo htmlspecialchars($data); а php-функция htmlspecialchars() позволит вывести на экран не сгенерированную html-страницу, а ее html-код. Для вывода xml-данных вывод страницы осуществляем через команду "принт" (печатать): print_r ($data); потому что имеем не просто текст, а массив данных. Внимание, если на сервере установлен модуль работы с xml, то гораздо удобней парсить данные не регом, а вытаскивать их из массива, тогда парсинг Алексы можно осуществить так:
<?php
  $url = 'isle-blog.ru';
  $link = 'http://data.alexa.com/data?cli=10&dat=snba&url='.$url;
  $data = file_get_contents($link);
  ...
  $alex_rank = (int)$xml->SD[1]->POPULARITY['TEXT'] ? (int)$xml->SD[1]->POPULARITY['TEXT'] : 'n/a';
?>

Но поскольку, как я выяснил, балуясь с Алексой, что у нее есть упрощенный xml-файл, то парсить в сто раз стало проще, быстрее (из-за маленького объема), тем более, что можно получить очень много данных, даже наличие сайта в каталоге Алексы и т.д. Находится данный файл по адресу:
$link = 'http://data.alexa.com/data?cli=9&dat=snba&url='.$url;
Я пока еще не все там разобрал и если кто знает API Alexa.com или знает, что обозначают строки, то пожалуйста, поделитесь ссылками или сообщите свои заметки в комментариях, был бы вам очень благодарен. Пример парсинга предположительно можно рассматривать такой:
<?php
  if (is_file($link)) { #Проверяем существует ли файл и можно ли его прочитать.
    $line = array(); #Объявляем массив для построчного чтения данных из файла.
    $fh = fopen($link,'r'); #Открываем файл для чтения данных.
    $fs = filesize($file); #Размер текстового файла (чтобы прочесть его весь).
    $data = fread($fh,$fs); #Читаем весь файл целиком.
    while (!feof($fh)) {$line[] = fgets($fh,4096);} #Читаем весь файл построчно.
    fclose($fh);
  } else echo 'Alexa Rank: n/a';
?>

Чтение прекращается при выполнении одного из следующих условий: -- из файла прочитано длина -- 1 байт; -- из файла прочитан символ новой строки (включается в возвращаемую строку); -- из файла прочитан признак конца файла (EOF). Таким способом можно получить массив, состоящий из строчек файла, типа: $arr[0] - первая строчка; $arr[1] - вторая строчка; $arr[2] - третья... После чего можно разбить каждую строчку прегами на составляющие, типа:
<?php
  preg_match('|(\d+)\s(.*?)\n|si',$data,$res);
  if ($res[1]==145) $alexa_rank = $res[2]:$res[2]?0;
  echo 'Alexa Rank: '.$alexa_rank;
?>

---------------------- Итак, вот что я узнал: 1-10 - $alexa_related_names (Related site, Names) 11 - $alexa_site_host (Например: habrahabr.ru) - хост сайта (имя домена). 69 - (s 0)//<CHILD SRATING="0"/> - рейтинг доступности информации для детей (Child Rating Scale (CRS): 0 - not at all; 1 - just a little; 2 - pretty much; 3 - very much.) 102 - $alexa_email (Может быть: "no data". Например: zgr@bk.ru) 104 - $alexa_email (Может быть: "Unlisted". Например: zgr@bk.ru) 105 - gamedev.net zwave.com (<DOS><DO DOMAIN="gamedev.net" TITLE="gamedev.net"/><DO DOMAIN="zwave.com" TITLE="zwave.com"/></DOS>) 108 - 17 //<REVIEWS AVG="4.5" NUM="17"/> 133 - ? www.dogpile.com/ 136 - 4.5 //<REVIEWS AVG="4.5" NUM="17"/> 139 - $alexa_speed (<SPEED TEXT="2360" PCT="49"/>) 140 - $alexa_speed_pct (<SPEED TEXT="2360" PCT="49"/>) 142 - $alexa_backlinks - внешние ссылки на сайт. 145 - 57 //<POPULARITY URL="ask.com/" TEXT="57"/> 147 - Online Since (Например: 04-Mar-2004) - дата регистрации в Алексе. 148 - $alexa_tel_fax (Может быть: "Unlisted". Например: +1 650 330 0100, Fax: +1 650 618 8571) 149 - $alexa_addr (Может быть: "['unlisted']". Адрес. Например: ["2705 N Carroll Ave", "Southlake, TX 76092", "USA"]) 150 - $alexa_owner_name (Может быть: "A9.com". Имя владельца сайта. Например: Zaiva Igor). //<OWNER NAME="ZWave, Llc"/> 151 - askj //<TICKER SYMBOL="askj"/> //<ADDR STREET="2705 N Carroll Ave" CITY="Southlake" STATE="TX" ZIP="76092" COUNTRY="US" /> 154 - $alexa_address_state (Штат. Например: "TX"). 155 - $alexa_address_city (Город. Например: "Southlake"). 156 - $alexa_address_country (Страна. Например: US). 157 - $alexa_address_street (Улица. Например: "157 2705 N Carroll Ave"). 158 - ? 159 - ? 160 - $alexa_site_dmoz (DMOZ) - наличие описания сайта в Алексе, предложенное его хозяином. 162 - ? (091096551X 1887902589 1552123073 0471246387 0843175931 1887902562 9875260762 0471126950 0473074818 0789463709 1882208285 1564841235 0966472608) 165 - $alexa_rank_reach (<REACH RANK="1783"/>, 3 month) 166 - ? Pageviews/User (3 month) 169 - askcom //<ASSOCS><ASSOC ID="askcom"/></ASSOCS> 170 - $alexa_rank_delta (<RANK DELTA="-440"/>, 3 month) 174 - 2 (Количество страниц, на каждой из которых до 10 ссылок) //<RLS PREFIX="http://" more="2"> 178 - ? 184 - ? Alexa RANK total today 189 - Кодировка и язык сайта. (Например: "x-unknown.utf-8", "en") //<LANG LEX="en"/> 191 - $alexa_site_name (Например: "Хабрахабр", "A9.com") - название сайта. 222 - Searching Multi-Search //<KEYWORDS><KEYWORD VAL="Searching"/><KEYWORD VAL="Multi-Search"/></KEYWORDS> 245-254 - $alexa_related_url (Related site, Links) isarchive 0 - ? А вот данные различных сайтов, сравните, например, Хабра: _http://data.alexa.com/data?cli=9&dat=snba&url=habrahabr.ru _http://data.alexa.com/data?cli=10&dat=snba&url=habrahabr.ru _http://alexa.com/siteinfo/habrahabr.ru _http://data.alexa.com/data?dat=snbaz&url=habrahabr.ru или _view-source:http://siteinfo.a9.com/data?cli=10&dat=snab&pane=amzn&ver=a9-1.5&url=lol.com а также других сайтов, например, google.ru. Данные xml lol.com:
<ALEXA VER="0.9" URL="lol.com/" HOME="0" AID="=">
<RLS PREFIX="http://" more="0"> 
  <RL HREF="www.phpbb.com/" TITLE="phpBB"/> 
</RLS> 
<SD TITLE="A" FLAGS="" HOST="lol.com"> 
  <TITLE TEXT="LOL.com - Funny 2.0"/> 
  <ADDR STREET="2705 N Carroll Ave" CITY="Southlake" STATE="TX" ZIP="76092" COUNTRY="US" /> 
  <CREATED DATE="10-Jan-1997" DAY="10" MONTH="01" YEAR="1997"/> 
  <PHONE NUMBER="+1 817 329 9242, Fax: +1 817 329 9243"/> 
  <OWNER NAME="ZWave, Llc"/> 
  <EMAIL ADDR="domains@zwave.com"/> 
  <DOS> 
    <DO DOMAIN="gamedev.net" TITLE="gamedev.net"/> 
    <DO DOMAIN="zwave.com" TITLE="zwave.com"/> 
  </DOS> 
  <LINKSIN NUM="649"/> 
  <SPEED TEXT="1265" PCT="78"/> 
  <CHILD SRATING="0"/> 
</SD> 
<SD> 
  <POPULARITY URL="lol.com/" TEXT="168274"/> 
  <REACH RANK="164351"/> 
  <RANK DELTA="-10481"/> 
</SD> 
</ALEXA>

Данные xml1:
<ALEXA VER="0.9" URL="habrahabr.ru/" HOME="0" AID="MPyBb1vxP400y5"> 
<RLS PREFIX="http://" more="2"> 
<RL HREF="lenta.ru/" TITLE="Lenta.ru"/> 
<RL HREF="artlebedev.ru/" TITLE="Студия Артемия Лебедева"/> 
<RL HREF="webplanet.ru/" TITLE="Вебпланета"/> 
<RL HREF="searchengines.ru/" TITLE="Searchengines.ru"/> 
<RL HREF="bash.org.ru/" TITLE="Цитатник Рунета"/> 
<RL HREF="re-store.ru/" TITLE="re:Store"/> 
<RL HREF="news2.ru/" TITLE="Новости 2.0"/> 
<RL HREF="erepublik.com/" TITLE="Erepublik.com"/> 
<RL HREF="opennet.ru/" TITLE="OpenNet"/> 
<RL HREF="linux.org.ru/" TITLE="Linux.org.ru"/> 
</RLS> 
<SD TITLE="A" FLAGS="DMOZ" HOST="habrahabr.ru"> 
<TITLE TEXT="Хабрахабр"/> 
<CREATED DATE="18-Apr-2006" DAY="18" MONTH="04" YEAR="2006"/> 
<PHONE NUMBER="+7 096 7848589"/> 
<OWNER NAME="Denis A Krjuchkov"/> 
<EMAIL ADDR="deniskin@gmail.com"/> 
<LINKSIN NUM="3527"/> 
<SPEED TEXT="2360" PCT="49"/> 
<CHILD SRATING="0"/> 
</SD> 
<DMOZ> 
<SITE BASE="habrahabr.ru/" TITLE="Хабрахабр" DESC="Социальное СМИ. Новости о блогах, поиске работы. Обзоры и рейтинги компаний."> 
<CATS> 
<CAT ID="Top/World/Russian/Компьютеры/Интернет/Новости_и_СМИ" TITLE="Интернет/Новости и СМИ" CID="349189"/> 
</CATS> 
</SITE> 
</DMOZ> 
<SD> 
<POPULARITY URL="habrahabr.ru/" TEXT="1581"/> 
<REACH RANK="1783"/> 
<RANK DELTA="-440"/> 
</SD> 
</ALEXA>

Данные xml2:
1 Linux.org.ru
2 OpenNet
3 Erepublik.com
4 Новости 2.0
5 re:Store
6 Цитатник Рунета
7 Searchengines.ru
8 Вебпланета
9 Студия Артемия Лебедева
10 Lenta.ru
11 habrahabr.ru
69 (s 0)
104 deniskin@gmail.com
139 49
140 2360
142 3527
145 1578
147 18-Apr-2006
148 +7 096 7848589
150 Denis A Krjuchkov
156 
157 
160 DMOZ
165 1783
166 721
170 -454
174 2
184 1487
191 Хабрахабр
245 linux.org.ru/
246 opennet.ru/
247 erepublik.com/
248 news2.ru/
249 re-store.ru/
250 bash.org.ru/
251 searchengines.ru/
252 webplanet.ru/
253 artlebedev.ru/
254 lenta.ru/
isarchive 0

Распечатка массива print_r():
SimpleXMLElement Object([@attributes] => Array(
  [VER] => 0.9
  [URL] => habrahabr.ru/
  [HOME] => 0
  [AID] => =
  )
  [RLS] => SimpleXMLElement Object([@attributes] => Array(
    [PREFIX] => http://
    [more] => 2
  )
  [RL] => Array(
    [0] => SimpleXMLElement Object(
      [@attributes] => Array(
        [HREF] => lenta.ru/
        [TITLE] => Lenta.ru
      )
    )
    [1] => SimpleXMLElement Object ([@attributes] => Array (
      [HREF] => artlebedev.ru/ [TITLE] => Студия Артемия Лебедева
    ) )
    [2] => SimpleXMLElement Object ([@attributes] => Array (
      [HREF] => webplanet.ru/ [TITLE] => Вебпланета
    ) )
    [3] => SimpleXMLElement Object ([@attributes] => Array (
      [HREF] => searchengines.ru/ [TITLE] => Searchengines.ru
    ) )
    [4] => SimpleXMLElement Object ([@attributes] => Array (
      [HREF] => bash.org.ru/ [TITLE] => Цитатник Рунета
    ) )
    [5] => SimpleXMLElement Object ([@attributes] => Array (
      [HREF] => re-store.ru/ [TITLE] => re:Store
    ) )
    [6] => SimpleXMLElement Object ([@attributes] => Array (
      [HREF] => news2.ru/ [TITLE] => Новости 2.0
    ) )
    [7] => SimpleXMLElement Object ([@attributes] => Array (
      [HREF] => erepublik.com/ [TITLE] => Erepublik.com
    ) )
    [8] => SimpleXMLElement Object ([@attributes] => Array (
      [HREF] => opennet.ru/ [TITLE] => OpenNet
    ) )
    [9] => SimpleXMLElement Object ([@attributes] => Array (
      [HREF] => linux.org.ru/ [TITLE] => Linux.org.ru
    ) )
  ) )

  [SD] => Array (
    [0] => SimpleXMLElement Object ([@attributes] => Array (
      [TITLE] => A
      [FLAGS] => DMOZ
      [HOST] => habrahabr.ru
    )
    [TITLE] => SimpleXMLElement Object ([@attributes] => Array (
      [TEXT] => Хабрахабр
    ) )
    [CREATED] => SimpleXMLElement Object ([@attributes] => Array (
      [DATE] => 18-Apr-2006
      [DAY] => 18 [MONTH] => 04
      [YEAR] => 2006
    ) )
    [PHONE] => SimpleXMLElement Object ([@attributes] => Array (
      [NUMBER] => +7 096 7848589
    ) )
    [OWNER] => SimpleXMLElement Object ([@attributes] => Array (
      [NAME] => Denis A Krjuchkov
    ) )
    [EMAIL] => SimpleXMLElement Object ([@attributes] => Array (
      [ADDR] => deniskin@gmail.com
    ) )
    [LINKSIN] => SimpleXMLElement Object ([@attributes] => Array (
      [NUM] => 3527
    ) )
    [SPEED] => SimpleXMLElement Object ([@attributes] => Array (
      [TEXT] => 2360 [PCT] => 49
    ) )
    [CHILD] => SimpleXMLElement Object ([@attributes] => Array (
      [SRATING] => 0
    ) )
    ) //[0] => ...

    [1] => SimpleXMLElement Object (
      [POPULARITY] => SimpleXMLElement Object ([@attributes] => Array (
        [URL] => habrahabr.ru/
        [TEXT] => 1581
      ) )
      [REACH] => SimpleXMLElement Object ([@attributes] => Array ([RANK] => 1783))
      [RANK] => SimpleXMLElement Object ([@attributes] => Array ([DELTA] => -440))
    )
    ) //[SD] => ...

    [DMOZ] => SimpleXMLElement Object (
      [SITE] => SimpleXMLElement Object ([@attributes] => Array(
        [BASE] => habrahabr.ru/ [TITLE] => Хабрахабр
        [DESC] => Социальное СМИ. Новости о блогах, поиске работы. Обзоры и рейтинги компаний.
      )
      [CATS] => SimpleXMLElement Object (
        [CAT] => SimpleXMLElement Object ([@attributes] => Array (
          [ID] => Top/World/Russian/Компьютеры/Интернет/Новости_и_СМИ
          [TITLE] => Интернет/Новости и СМИ
          [CID] => 349189
        ) ) //[CAT] => ...
      ) //[CATS] => ...
      ) //[SITE] => ...
    ) //[DMOZ] => ...
  )

Тырить облегченный вариант было бы очень удобно обычными прегами, но поскольку они тяжелые, то отпарсить xml-данные можно строковыми функциями, используя цикл (поскольку строковые функции работают гораздо быстрее, не нагружая сервер) - у кого как хватит фантазии. wink
if (strpos($data,'1 ')) {}
...
if (strpos($data,'254 ')) {}

Кстати, в адресе _http://data.alexa.com/data?cli=10&dat=snba&url=site.ru строка "&dat=snba" отвечает за вывод различных элементов. Например, "&dat=n" выводит:
<RLS PREFIX="http://" more="2">
<RL HREF="lenta.ru/" TITLE="Lenta.ru"/>
<RL HREF="artlebedev.ru/" TITLE="Студия Артемия Лебедева"/>
<RL HREF="webplanet.ru/" TITLE="Вебпланета"/>
<RL HREF="searchengines.ru/" TITLE="Searchengines.ru"/>
<RL HREF="bash.org.ru/" TITLE="Цитатник Рунета"/>
<RL HREF="re-store.ru/" TITLE="re:Store"/>
<RL HREF="news2.ru/" TITLE="Новости 2.0"/>
<RL HREF="erepublik.com/" TITLE="Erepublik.com"/>
<RL HREF="opennet.ru/" TITLE="OpenNet"/>
<RL HREF="linux.org.ru/" TITLE="Linux.org.ru"/>
</RLS>

Например, "&dat=s" выводит:
<SD TITLE="A" FLAGS="DMOZ" HOST="habrahabr.ru">
<TITLE TEXT="Хабрахабр"/>
<CREATED DATE="18-Apr-2006" DAY="18" MONTH="04" YEAR="2006"/>
<PHONE NUMBER="+7 096 7848589"/>
<OWNER NAME="Denis A Krjuchkov"/>
<EMAIL ADDR="deniskin@gmail.com"/>
<LINKSIN NUM="3527"/>
<SPEED TEXT="2360" PCT="49"/>
<CHILD SRATING="0"/>
</SD>

Что выводят остальные буквенные коды - не знаю. Ну, в общем-то вот и всё. Кому интересно, пишите, спрашивайте, постараюсь ответить на все вопросы. Буду рад, если кто поделится и своими советами.
Добавлено: 24 Августа 2013 11:15:15 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...