Пример работы с PHP Simple HTML DOM Parser
Автор: SysaninФев 28
Попросили в комментариях поста, где я рассказывал про PHP Simple HTML DOM Parser, написать более подробно о работе с ним. В качестве примера набросал небольшой парсер для перво попавшегося интернет магазина.
Предположим, мы имеем страницу http://business-service.shop.by/3/ (хотя, конечно, парсер съест любую страницу с каталогом товаров для данного сайта) и с каталога нам надо брать название товара, ссылку по которой можно прочитать полное описание и краткое описание товара.
Вот код который будет это делать, краткие комментарии в коде, расширенные после:
# пример парсинга http://business-service.shop.by/3/
include('simple_html_dom.php');
$text = file_get_html('http://business-service.shop.by/3/');
$i=0;
# ищем ссылки по которым можно найти полное описание
foreach ($text -> find('h2.tovarhead a') as $temp){
# сейчас мы имеем нечто вроде <a title="Nokia 1200" href="99/">Nokia 1200</a>
# достаним урл
if(preg_match('/href=".*">/i', $temp, $result)){
$out['link'][$i] = 'http://business-service.shop.by/3/'.substr($result[0], 6, strlen($result[0])-8);
}
#достаним название продукта
$out['title'][$i] = strip_tags($temp);
$i++;
}
$i=0;
# ищем описание продуктов
foreach ($text -> find('td.textinfo2 div.desc') as $temp){
$out['text'][$i] = strip_tags($temp, '<br>');
$i++;
}
print_r($out);
?>
Первым делом подключаем библиотеку с PHP Simple HTML DOM Parser.
Дальше смотрим структуру документа:
<tr><td class="textheader" colspan="3"><h2 class="tovarhead"><a title="Nokia 1200" href="99/">Nokia 1200</a></h2></td></tr>
...
Вот наше заглавие и адрес ссылки на полное описание. Если посмотреть все остальное, становиться понятно, что такой класс встречается только в заглавии товара. Значит для заголовка нам нужно вытянуть содержимое тега <a>, который является потомком тега <h2> с классом "tovarhead". Если вспомнить jQuery, то для того чтобы обратиться к данной ссылке необходимо произвести поиск 'h2.tovarhead a', что и значит сказанное ранее. В принципе дописывать в поиске тег <a> не обязательно, так как <h2> и так содержит только ссылку.
После обработки библиотекой получим массив вроде:
[1] => '<a title="Nokia 1208" href="265/">Nokia 1208</a>'
[2] => '<a title="Nokia 1600" href="588/">Nokia 1600</a>'
...
Далее регуляркой вытягиваем строку href="ТУТ_ОКОНЧАНИЕ_УРЛА", выделяем на что оканчивается ссылка, добавляем начало из константы (ну или как нам будет удобней) и получаем урл на полное описание. Если б на сайте писали абсолютный линк было б конечно удобнее.
Название продукта легко получается из прошлого массива, просто удалением тегов.
Далее описание продукта нужно вытягивать из кода вроде этого:
<td class="textinfo2">
<div class="desc" onselectstart="return false">оригинал,русская клавиатура,гарантия 36 месяцев, цвет Черный.<br>В комплекте: зарядное устройство, инструкция на русском языке.<br><br>О наличии уточнять дополнительно.<br><br>Доставка по г. Минску бесплатно.<br>
</div>
<div class="compareline" style="float: right; position: relative; top: 4px; bottom: 5px;">
...
Тут, как видим, в ячейке с классом textinfo2 содержится несколько дивов и один из них нужен нам. Соответственно вытягиваем описание командой 'td.textinfo2 div.desc' То есть ищем <div> с классом desc, который является потомком тега <td> с классом textinfo2.
В итоге работы скрипта получаем что-то такое:
(
[link] => Array
(
[0] => http://business-service.shop.by/3/99/
[1] => http://business-service.shop.by/3/265/
[2] => http://business-service.shop.by/3/588/
[3] => http://business-service.shop.by/3/9/
[4] => http://business-service.shop.by/3/309/
[5] => http://business-service.shop.by/3/636/
[6] => http://business-service.shop.by/3/10/
[7] => http://business-service.shop.by/3/592/
[8] => http://business-service.shop.by/3/100/
[9] => http://business-service.shop.by/3/101/
)
[title] => Array
(
[0] => Nokia 1200
[1] => Nokia 1208
[2] => Nokia 1600
[3] => Nokia 1600
[4] => Nokia 1650
[5] => Nokia 1680
[6] => Nokia 2310
[7] => Nokia 2600
[8] => Nokia 2610
[9] => Nokia 2626
)
[text] => Array
(
[0] => оригинал,русская клавиатура,гарантия 36 месяцев, цвет Черный.<br>В комплекте: зарядное устройство, инструкция на русском языке.<br><br>О наличии уточнять дополнительно.<br><br>Доставка по г. Минску бесплатно.<br>
[1] => СТБ, РСТ. C русской клавиатурой, гарантия 36 месяцев, цвет Черный.<br>В комплекте: зарядное устройство, инструкция на русском языке.<br><br>О наличии уточнять дополнительно.<br><br>Доставка по г. Минску бесплатно.<br>
[2] => СТБ, РСТ, цвет черный, гарантия 36 месяцев.<br>В комплекте: зарядное устройство, инструкция на русском языке.<br><br>О наличии уточнять дополнительно.<br><br>Доставка по г. Минску бесплатно.<br><br>
[3] => Оригинал с русской клавиатурой, гарантия 36 месяцев, цвет Серебро.<br>В комплекте: зарядное устройство, инструкция на русском языке.<br><br>О наличии уточнять дополнительно.<br><br>Доставка по г. Минску бесплатно.<br>
[4] => оригинал, цвет черный, гарантия 36 месяцев.<br>В комплекте: зарядное устройство, инструкция на русском языке.<br><br>О наличии уточнять дополнительно.<br><br>Доставка по г. Минску бесплатно.<br><br>
[5] => c Русской клавиатурой. цвет черный, гарантия 36 месяцев.<br>В комплекте: зарядное устройство, .<br><br>О наличии уточнять дополнительно.<br><br>Доставка по г. Минску бесплатно.<br><br>
[6] => РСТ,СТБ. С русской клавиатурой, гарантия 36 месяцев, цвет Серебро с черным.<br>В комплекте: зарядное устройство,наушники, инструкция на русском языке.<br><br>О наличии уточнять дополнительно.<br><br>Доставка по г. Минску бесплатно.<br>
[7] => С русской клавиатурой, гарантия 36 месяцев, цвет Черный.<br>В комплекте: зарядное устройство,наушники, .<br><br>О наличии уточнять дополнительно.<br><br>Доставка по г. Минску бесплатно.<br>
[8] => Оригинал с русской клавиатурой, гарантия 36 месяцев, цвет Черный.<br>В комплекте: зарядное устройство, <br>инструкция на русском языке.<br><br>О наличии уточнять дополнительно.<br><br>Доставка по г. Минску бесплатно.<br><br>
[9] => СТБ, РСТ C русской клавиатурой, гарантия 36 месяцев, цвет черным.<br>Полный комплект.<br><br>О наличии уточнять дополнительно.<br><br>Доставка по г. Минску бесплатно.<br>
)
)
11 коммент.
Пишет Samsung | дата: 15 марта 2009 в 10:12
Спасибо большое. Но мне кажется, что для парсинга XML лучше подходит Simple XML, а для сложных манипуляций с HTML - свой парсер, универсальный
Пишет Sysanin | дата: 15 марта 2009 в 11:44
на счет XML согласен, а вот под HTML писать с использованием Simple HTML DOM порядком быстрее, конечно, если вам очень критична производительность, лучше самому писать. Хотя все дело вкуса
Пишет Diverse | дата: 18 марта 2009 в 11:17
а я думаю то что надо…
уже написал парсер yandex.market, правда пока только страни самого товара, но скоро сделаю и перебор всех товаров в нужной категории…
в данном случае скорось нафиг ненужна, а удобство написания навысоте… )
Пишет Sysanin | дата: 18 марта 2009 в 16:35
тут главное соблюдать баланс между скоростью написания, производительностью, качеством и бюджетом:)
Пишет Парсим HTML через DOM | Формата.нет | дата: 3 апреля 2009 в 22:11
[...] как можно удобно парсить html файлы с помощью класса PHP Simple HTML DOM Parser используя синтаксис известной JS библиотеки jQuery. Но у [...]
Пишет дима | дата: 23 августа 2009 в 15:17
а как вытащить из таблицы строки tr ?
Пишет Sysanin | дата: 23 августа 2009 в 22:30
$text -> find(’tr’)
так получим все содержимое строк
Пишет Николай | дата: 1 сентября 2009 в 7:12
вот так вот
find(’h2.tovarhead a’)
мы получаем массив объектов
поэтому вовт так вот
if(preg_match(’/href=”.*”>/i’, $temp, $result))
это полный бред
+ к тому что бы достать ссылку можно обратиться к атрибуту тэга а - href и получить ссялку
зачем вот это ? strip_tags($temp, ”)
если там есть специальный метод plaintext ??
какой-то странный код, вы тут показали…
Пишет Photon | дата: 21 марта 2010 в 8:21
Вот только при обработке даже относительно простых страниц потребление памяти очень высокое. А так да, удобная штука.
Пишет Виталий | дата: 22 апреля 2010 в 18:27
Автор забыл добавить, что у этой библиотеки после завершения работы надо чистить память, то есть перед повторным применением переменной с объектом DOM надо ее очистить, иначе память заканчивается после нескольких итераций (на себе проверено
)
То есть если переменная называется как у автора $text, то
$text->clear();
unset($text);
Об этом кстати и в факах на офсайте написано
Пишет Артур | дата: 9 мая 2010 в 13:22
Николай + 1, человек использует библиотеку, не зная встроенных методов. А может ну его вообще, тогда этот simple html dom парсер и обойтись preg_match?