Частенько в сети можно найти различные способы парсинга сайта 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>
Что выводят остальные буквенные коды - не знаю. Ну, в общем-то вот и всё. Кому интересно, пишите, спрашивайте, постараюсь ответить на все вопросы. Буду рад, если кто поделится и своими советами.