Парсим сайты с phpQuery
На моей практике довольно часто встречались задачи вроде: спарсить таблицу с какого-то сайта в csv-файл, сграбить картинки с какого-то сайта и т.д. Все эти задачи можно обобщить термином парсинг сайтов. Большинство из нас, как и я раньше для решения таких проблем использовали стандартные средства php для парсинга xml-файлов (html все-таки является подвидом xml) совместно с регулярными выражениями.
Скрипты получались довольно громоздкими и непонятными. К счастью для себя, я недавно наткнулся на библиотеку под названием phpQuery (http://code.google.com/p/phpquery/), которая является портированным jQuery в php.
Если Вы пользовались jQuery, то должны знать о его очень удобном механизме селекторов, который мог бы быть чрезвычайно полезным при парсинге сайтов.
Допустим у нас есть такой кусок кода:
<ol class="results" start="1"> ... <li> <div class="title"> <i style="background-image: url(http://favicon.yandex.net/favicon/www.medvedev-da.ru);"/> <a target="_blank" href="http://www.medvedev-da.ru/" onmousedown="w(this,'80.22.82','84=85,186=80');" tabindex="2">Дмитрий <b>Медведев</b> - Главная</a> </div> <div class="text"> <span>"Правительству нужно действовать незамедлительно, бегом!" - Итоги <wbr/>2008 года - взгляд Президента России Дмитрия <b>Медведева</b>.</span><br/> </div> <div class="info"> <span style="color: rgb(0, 102, 0);"> www.medvedev-da.ru · 9 КБ </span> </div> <div class="info"> <nobr><a target="_blank" href="...">Сохраненная копия</a></nobr> · <nobr><a onmousedown="..." href="...">Еще с сайта</a> <span class="count">39241</span></nobr> · <nobr>Рубрика: <a href="..." onmousedown="w(this,'80.83','84=85');">Политика</a></nobr> </div> </li> ... </ol>
Это код обычной страницы с результатами поиска Yandex`а по запросу “медведев”.
Нам нужно спарсить title страницы-результата, ее краткое описание и адрес страницы.
С помощью phpQuery, код будет примерно таким:
<?php
ini_set('max_execution_time', '0');
error_reporting(E_ALL);
define('URL', 'http://yandex.ru/yandsearch?text=медведев');
require('phpQuery.php');
$results_page = get_xml_page(URL);
$results = phpQuery::newDocument($results_page);
$elements = $results->find('ol.results > li');
$info = array();
foreach ($elements as $element){
$title = pq($element)->find('div.title > a');
$title = pq($title)->text();
$descr = pq($element)->find('div.text > span');
$descr = pq($descr)->text();
$link_text = pq($element)->find('div.info:first > span');
$link_text = pq($link_text)->text();
$link_text = explode('•', $link_text);
$link = trim($link_text[0]);
$info[] = array('title' => $title, 'descr' => $descr, 'link' => $link);
}
print_r($info);
function get_xml_page($url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$page = curl_exec($ch);
curl_close($ch);
return $page;
}
?>
Как видите, код довольно понятный и его можно очень легко модифицировать при необходимости. Что касается самой библиотеки phpQuery, в этой статье я рассмотрел лишь часть ее возможностей на примере парсинга сайтов. На самом деле, с ее помощью можно так же легко модифицировать структуру документа html и еще много другого.
Более подробную документацию к ней можно найти в блоге ее разработчика: http://phpquery-library.blogspot.com/.
На этом все. Удачи!
P.S.:
В связи с переездом FeedBurner`а в Google, адрес нашей RSS-ленты изменился на . Измените его в Ваших ридерах если уже подписаны и подписывайтесь на него в противном случае
Повторяю: Новый адрес нашего RSS-фида – .
Январь 26th, 2009
[...] удобно, практично. А вчеру увидел порт jQuery на php. Вот тут хороший пример использования библиотеки. Рубрика: [...]
Январь 26th, 2009
http://i-novice.net/zheltaya-knopka-rss/
>Наш адрес – .
исправьте
Январь 26th, 2009
2 adw0rd: Спасибо. Я и забыл про эту страницу
Январь 27th, 2009
Спс, не знал про такое. Сам странички парсил с помощью Snoopy
Январь 28th, 2009
Актуально
Январь 29th, 2009
еще есть не плохая софтинка webharvest опенсурс.
быстро и удобно
это тоже интерессный вариант, надо попробовать
Январь 30th, 2009
Классная вещь.
У меня один вопрос :
Яндекс он в utf-8 выдает результаты поиска.
А если сайт в win-1251 , то у меня кракозябры выскакивают.
Январь 31st, 2009
Посмотрите в сторону функции iconv
Февраль 19th, 2009
Если будете часто парсить, можно на бан по IP влететь ) Я уже пару раз влетел.
Февраль 27th, 2009
ктонибудь сравнивал скорость парсинга на phpQuery с регекспами?
Март 15th, 2009
Что то не работает код, может структура Яндекса поменялась?(
Март 17th, 2009
Вполне возможно, но лучше включить вывод ошибок и проверить нет ли какой-то ошибки или предупреждения.
Март 19th, 2009
А разве строка error_reporting(E_ALL); не говорит выводить все ошибки и предупреждения?
Ошибок нету, просто массив пустой(
Апрель 9th, 2009
чтот ругается…
Fatal error: Call to undefined function curl_init()
Апрель 9th, 2009
Олег, Вам нужно подключить модуль cURL в php.ini:
extension=php_curl.dll
Апрель 9th, 2009
Спасибо за ответ. Потом пришлось еще и dom включать…
Теперь не могу понять, как настроить. На удаленном источнике нет id вообще. Там верстка только таблицы и классы.
Что можно писать в find ? Какой синтаксис?
Пишу
$elements = $results->find(’table’); //
…
$title = pq($element)->find(’a');
$title = pq($title)->text();
это не работает
Апрель 10th, 2009
Синтаксис параметра find очень похож на селекторы в css и jquery. Ознакомься с ним и заодно используй команду echo в php, для вывода промежуточных результатов.
Июль 24th, 2009
Скрипт выдаёт ошибку:
Fatal error: Call to undefined function curl_init()
как исправить???
Август 23rd, 2009
К PHP не подключена библиотека CURL, поэтому выдается такая ошибка.
Август 28th, 2009
Что б не было кракозябр с яндекса в начало страницы
header(’Content-type: text/html; charset=utf-8′);
Сентябрь 3rd, 2009
Html не является подвидом xml. Подвидом xml является xhtml.
Октябрь 2nd, 2009
А что будет если в коде сайта есть ошибки, например неправильно вложенные теги (………)?
Парсер “ниасилит”?
Апрель 24th, 2010
так и не нашел документации. пытаюсь найти аналог метода в jQuery “attr”, пока безуспешно
Сентябрь 1st, 2010
Даний скрипт создает масив значений што делать эсли нужна заливать в базу все промежуточние значения а не масив целиком.