Как стать автором
Обновить

Комментарии 80

А вот ещё интересная библиотека htmlSQL(https://github.com/hxseven/htmlSQL), позволяет работать с dom-элементами с помощью запроса напоминающего SQL

Например, SELECT href,title FROM a WHERE $class == «list»
href, title — вернуть атрибуты
a — в каких тегах искать
$class == «list» — аттрибут class=«list»
Спасибо, добавлю в конец статьи. Если у кого-то есть еще примеры, пишите, может получиться интересная подборка.
вот я… чудак, прикрутил simple html dom в качестве сервиса недавно, хотя есть штатное средство (

спасибо
Изначально поэтому и полюбился мне jQuery, хотя у них не только заимствованные из css селекторы есть, но в основном вы абсолютно правы:

Borrowing from CSS 1–3, and then adding its own, jQuery offers a powerful set of tools for matching a set of elements in a document.

И спасибо за ссылку на zend.
Увы, уже было
Из-за «recovery mode» голосовать за топик не стал.
Я отмечал это в самом начале топика.
Справедливости ради, следует указать, что похожий пост уже присутствует на habrahabr, но на мой взгляд, содержит слишком малое количество информации

Причем в использовании она пожалуй удобнее, ближе к jQuery.
Например:
$pq->find('Item#id')->text();
$pq->find('Item#id')->attr('class', 'new-class');
$pq->find('Item#id')->children('.sub-item')->html();

Интересно было бы услышать от автора о преимуществах PHP Simple HTML DOM Parser перед phpQuery.
Посмотрю и ближе к вечеру отпишусь из видимых только то, что phpQuery остановился в развитии в 2009 году судя по гуглкоду. Про сам код пока ничего сказать не могу.
simple html dom в сущности поддерживает тоже самое только названия другие.
Тут разница что там Pear, тут либа которая качается с каждым проектом. Зачастую это важно.
Автор пожалуйста упомяните в статье что file_get_contents() не лучший способ получать html со странички, он достаточно часто не работает на многих сайтах, к тому же вы не сможете получить http код, самый яркий пример когда вам выдало 404 страничку.

Можно использовать например curl. Лично я использую в простых проектах эту простую функцию: gist.github.com/Fedcomp/5383203 (возможный быдлокод)
Если вы имеете ввиду file_get_html то вы не правы: i.imgur.com/Za3Pea8.png
Если вы говорите про str_get_html то я про него и говорил. Скачать через курл и передать классу в виде строки.
Возможно вы имели ввиду что то еще?
Ошибся, каюсь. На данный момент file_get_html не отдает вообще ничего с 404 страницы. Добавил проверку по заголовку страницы в скрипт. Спасибо за замечание.
Добавил проверку по get_headers. Новый скрипт можно взять тут
Насчет «часто не работает на многих сайтах» не знаю, но вот в остальном эта функция хорошо настраивается: www.php.net/manual/ru/context.php
и 404-ю получить можно и даже редиректы отменить и пр. Конечно это не отменяет заслуг curl, но и так категорично говорить о file_get_contents я бы не стал.
Посыпаю голову пеплом, я не знал про эту функциональность.
В своём проекте использую. Не устраивала было скорость, решил сравнить на одной и той же странице:
1. simple_html_dom — 5.5 сек
2. nokogiri — 0.07 не работают выборки типа tr[id^=someid] и прочие сложные, нужные мне. Не подошло
3. ganon — 68 сек (!) — увы.
4. встроенный XML DOM не позволяет делать хоть сколько нибудь сложные выборки,
как например в simple_html_dom ($item->find('p[class=one-product-description-title] a',0)
5. htmlSQL — 0.09 сек. — неплохо, но результаты выборки не являются объектами как в simple_html_dom, что критично.

Остался на simple_html_dom.
А phpQuery не тестировали?
Если парсить тот же твиттер (или подобные этому задачи рассматривать) можно кешировать и скрипт по сути будет отрабарывать раз в 10-30 минут. А вот для каких то более сложных задач думаю будет заметно. Сегодня попробую потестировать все библиотеки на страничке rbc, например.
У твиттера есть же апи?
Последние нововведения в API твиттера меня не радуют. Мне проще спарсить то, что нужно самому.
А какие селекторы юзаете? и как много? может дело не в парсере, а где то утечка производительности?
Тут лаги происходят не во время выборок (они быстро делаются) а во время загрузки HTML в парсер.
Сейчас разрабатываю вторую версию своей старой DOM библиотеки. Интересно мнение тех, кто использует альтернативные. Если будет время/возможность, посмотрите пожалуйста — работает ли моя разработка в вашем случае. Сложные и даже очень сложные селекторы есть в функционале.

Описал библиотеку и функционал подробнее ниже.
встроенный XML DOM не позволяет делать хоть сколько нибудь сложные выборки

О чем это вы?
встроенный XML DOM позволяет делать выборки любой сложности и намного гибче CSS
Ну вот у меня есть выборка типа: $trs = $this->dom->find('tr[id^=row]');
Разве XML DOM так может (имею в виду id^=row)?
Конечно может, учитывая что большенство библиотек трансформируют CSS в XPATH и выполняют его.
Например используя SimpleXml это будет выглядить приблизительно так:
$xml = simplexml_load_string($xml);
$trRow = $xml->xpath('//tr[starts-with(@id, "row")]');

Ну совсем ппц. Ну откройте так любимые PHP'шниками доки и посмотрите список классов модуля. Потом почитайте зачем каждый из них нужен. Я давно уже считаю, что Хабр деградировал, но что настолько…
Он может даже даже в стандартные XPath выражения добавлять свои функции.

Лучше XPath пока ни чего не видел. Активно использую его в парсере html страниц каталога товаров.
Говорят tidy самый быстрый (хорошо бы добавить в бенч), так как в виде Extension на C, но возможно некоторых вещей он не умеет.
раз сделан как расширение — есть проблема кроссплатформенности (на домашнем win — на продакшене Linux)
Это же стандартно есть в PECL везде.
Товарищи, вот монстр по парсингу, использую его в нескольких проектах: querypath.org/
однажды нужно было выдрать из буферизированного html блок с определенным классом. Описанная в посте библиотека потерпела фиаско, как и упомянутый выше querypath, справилась только, опять же, упомянутая выше phpQuery. Так что рекомендовать могу только её, остальные у меня уже доверия не вызывают
А можно конкретный пример если не сложно?
$class = ".".trim($_GET['select']);
$html = phpQuery::newDocument($APPLICATION->EndBufferContent());
$params['html'] = pq($class)->htmlOuter();

в $_GET['select'] приходит требуемый класс. Simple HTML DOM Parser ничего не находил, как и querypath
Есть еще моя старая библиотечка: github.com/amal/CDom

  • jQuery подобное API
  • Автоматическое определение кодировки. Умеет читать кодировку указанную в самом html и некоторую эвристику для остальных случаев (не идеальное, но работает)
  • Поддерживает XML/HTML любой степени кривизны и поврежденности (насколько вообще возможно поддерживать)
  • Полная поддержка CSS3 селекторов и дополнительных «jQuery selector extensions»
  • Возможности по манипуляции DOM и экспорту результата
  • Умеет экспортировать HTML в текст с учетом блочных тегов, переводов строк и т.п.
  • Код покрыт тестами
  • Может работать также с простым BBCode и другими HTML подобными разметками

Сейчас как раз работаю над второй версией (с composer, PSR-0, переработанным парсером и прочими плюшками). Скорее всего напишу сравнительно-обзорную статью на хабре, как закончу.
Кто то обьяснит, почему используются библиотеки для имуляции css, вместо более продвинутого, скоростного и нативного xpath?
Для тех, кто уже знает CSS или jQuery-селекторы, XPath — это ещё один язык, который надо изучать, и который, к тому же, теряет популярность: www.google.com/trends/explore#q=xpath
Ну во-первых, он очень прост — так что если вдруг кто то его не знает то лучше потратить час два на изучение
Во-вторых для PHP существует SimpleXML API которое позврляет сдельть все тоже, и так само выразительно, без внешних зависимостей

Имхо, CSS это вообще сплошное недорозумение

Он очень легко и просто изучается. Буквально осенью привлекал фронта на написание XPath выражений для парсера каталогов. Человек не знающий что такое DOM API, не представляющий что есть XML и ни разу не видевший XPath через 2 часа уже писал первые выражения для парсера. Еще где-то часа 2 ушло на получение требуемых выражений. Конечно, это потребовало не самостоятельного изучения, а я объяснял общий концепт и ткнул в нужные места спецификации. Но человек на следующий день уже сам делал следующий парсер, а я лишь контролировал конечный результат.

Так что… я могу утверждать, что Xpath это достаточно легко осваиваемая идея.
С XPath все отлично, но вот PHP DOM имеет ряд серьезных недостатков, как то неудобное API (собственно, как и в браузерах, из-за чего в свое время набрал популярность jQuery), плохая поддержка html (на самом деле плохая, я встречал сотни html документов, которые не мог обработать DOMDocument/SimpleXML), фактическая невозможность получить на выходе все тот же html (например выбрать конкретные узлы и получить их код ТОЧНО как в исходном документе).
неудобное API
— дело вкуса и всегда можна сделать обертку
плохая поддержка html
— с этим могу частично согласиться, так как действтельно все плохо с невалидным html. И это скорей связано с тем что все браузеры/движки разбора html востанавливали его поразному, пока не появился стандарт разбора в html5.
получить их код ТОЧНО как в исходном документе
— вполне возможно, вот только интересно зачем это вам?
плохая поддержка html

Точного стандарта нет, но как разбирать вполне понятно. Даже хоть как нибудь было неплохо. Но как уже писал, встречал сотни html документов, которые вообще не мог обработать DOMDocument/SimpleXML. Целые куски обрабатывались некорректно, как-то корежились… в общем ад. При этом своей библиотекой или simple html dom обрабатывал спокойно.

получить их код ТОЧНО как в исходном документе

С этим встречался в очень многих задачах. XML DOM иной раз меняет исходный код достаточно сильно, «достраивая» код до валидного XML, что совершенно неприемлемо. Сделать то что-то можно при желании, но только с обертками и кучей костылей, что опять же не вариант. Нужен именно HTML DOM, причем заточенный под задачи парсера, а не рендеринга HTML (т.е. достраивать вообще что либо не нужно, надо обрабатывать как есть).
Подтверждамс — при вкуривании (небольшого) мануала — работа с библиотекой лаконична.
Недостатки, повторюсь: медленный парсинг (не выборка) и утечки памяти, которые вроде в посдедней версии решены.
там вроде были методы для очистки памяти.
1. Т.к. парсер целиком на PHP, то работать будет медленно и памяти будет есть заметно больше, чем какой-нибудь биндинг к libxml2.

2. Зачем-то без разрешения вырезает script, CDATA, style и ещё много информации
php > require '/tmp/simple_html_dom.php';
php> $html = '
<html>
<body>
  bodytxt1
  <script>var y = a<b;</script>
  <style>body {display:none}</style>
  <p>I-m here</p>
  bodytxt2
</body>
</html>';
php > $tree =  str_get_html($html);
php > echo $tree->find("body", 0)->plaintext;
bodytxt1 I-m here bodytxt2
php > 
php > echo $tree->find("body > p", 0)->plaintext;
I-m here
php > 
php > echo $tree->find("body > script", 0)->plaintext;
php > 


3. Не умеет преобразовывать HTML entities

php > $html = '<html><body>M&amp;M-s, 3&gt;2</body></html>';
php > $tree =  str_get_html($html);
php > echo $tree->find("body", 0)->plaintext;
M&amp;M-s, 3&gt;2
php > 


Вывод можете сами сделать.
1. libxml не даст таких хитровымудренных запросов, типа [attribute*=value] (есть такие верстальщики, использующие (почти) одинаковые классы при верстке рекламных блоков и блоков с контентом

2. Библиотека для парсинга данных — нужно ди извлекать скрипты и стили?

3. Поможет htmlspecialchars_decode
1. Use XPath, Luke!
2. В них тоже могут быть данные
3. Ок
Кто-нибудь (пожалуйста, пожалуйста, пожалуйста :) добавьте парсеры, упомянутые в этой статье к набору тестов в этом постинге. Ну очень любопытно…
Я постараюсь протестить максимум парсеров, которые хотя бы косвено здесь упоминались.
А как с обработкой ошибок? Мне как в том меме «Обычно я не парсю html, но если парсю, то в нем куча синтаксических ошибок». С этой стороны лучше всего себя ведут nokogiri и родной, но медленноватый и сложный Document Object Model.
Юзал эту библиотеку одно время.
В ней тогда была утечка памяти — постоянно вылетала при работе в демонах.
Штатная функция очистки не помогала.
Решил проблему с помощью хака: загрузки в объект пустой строки:

$html->load('');
Да, на php подобных библиотек как говна за баней, как у дурака фантиков. Поражает энергия авторов этих поделий, из-за того чтобы подфиксить что-то в открытом проекте пишут с нуля новый. Ну дай бог, раз силы есть.
Потом перестают поддерживать свой проект и чтобы пофиксить баги приходится создавать новый и так далее до бесконечности, это да.
Программы они же как дети, ну и что, что у соседа их три, а я своих хочу :))) Ну, а раса PHP очень плодовитая…
Чужими детьми ты пользоваться не можешь или детей ты можешь склонировать и исправить ошибки. Не раса, а масса. И не плодовитость это, а злокачественное какое-то деление.
Да проститься мне неполиткорректность, считайте их китайскими детьми
Неполиткорректность — может быть, но мягкий знак — сшивать вам за такое указательный и средний пальцы правой руки.
> simple_html_dom.php 1742 lines (1546 with data), 54.9 kB

Oh, you must be joking.
Для одного из проектов пробовал разные подобные библиотеки, но в итоге остановился на Simple HTML DOM Parser.

Его минусы:
1) Не очень высокая скорость работы (есть библиотеки, бьющие его наповал по этому параметру)
2) Просто жуткий код — потребовалось расширить некоторые его методы, так умом рухнуть можно, пока вникнешь в логику

Но есть один плюс, который в моем случае перевесил все: т.к. все парсится чисто своим кодом, без всяких внешних DOM-библиотек, то с его помощью можно не только парсить отдельные куски HTML-кода (что другие парсеры часто понимают, как невалидный код), но и вносить в него изменения, не ломая исходной структуры. Аналогов, которые умеют делать то же самое, но при этом в чем-то превосходят Simple HTML DOM Parser, я просто не нашел
Попробуйте CDom :)
habrahabr.ru/post/176635/#comment_6137137

По крайней мере второй недостаток я в нём решил. С первым недостатком некоторые улучшения ожидаются в новой версией.
А все фичи также есть, даже больше и удобнее.
НЛО прилетело и опубликовало эту надпись здесь
Мало того, при больших объемах парсинга можно натолкнуться на segmentation fault (даже с учетом переодической очистки памяти через ->clear() и unset() ). Подробней — kirugan.ru/2013/01/kak-borotsya-s-segmentation-fault-v-simple_html_dom/
Скажите, какая максимальная величина файла, который сможет «обработать» simple_html_dom?
Столкнулся с тем, что библиотека как бы не видит xml-файл величиной в 18 мегабайт (237425 строк).
file_get_html и str_get_html возвращают false.
На мелких файлах отрабатывает без проблем.
Ограничения памяти и времени выполнения в php позволяют спокойно пережевать этот файл.
Чуть позже выложу статью со сравнением библиотек для парсинга, постараюсь подробнее расписать на счет вашего вопроса. Пока что посмотрите обсуждение на SF
Здравствуйте.
Есть html код:

div class=«title» data-action=«open» data-params='test'

Как при помощи simple_html_dom получить содержимое атрибута data-params?

Логически это должно выглядеть так: $dom = $html->find('div[class=title]', 0)->data-params
Но, как вы понимаете, это не работает.
всего лишь предположение (просто первое, что пришло на ум — проверить нет возможности):

$attr = 'data-params';
$dom = $html->find('div[class=title]', 0)->$attr


А вообще, если есть возможность, попробуйте phpQuery
Я сделал так
$dom = $html->find('div[class=title]', 0)->attr['data-params'].
НЛО прилетело и опубликовало эту надпись здесь
Сам отказался от этой библиотеки в пользу tidy+xpath, оп тестам производительности она показала самый плохой результат, к сожалению сами тесты потеряны.

На счет ошибки, попробуйте получить страницу через file_get_contents и посмотреть что возвращает.
Simple PHP DOM Parser — глючное говно (врожденные проблемы с выпадением в рекурсии, неспособность выдрать tbody без thead, невозможность выбрать вторую ссылку в ячейке таблицы по find('a') и так далее и тому подобное). Как оказалось в середине проекта, когда уже поздно метаться в сторону других библиотек. Имейте это ввиду, когда будете выбирать что использовать.
Вообще, я обещал обзор списка библиотек и возможно таки сделаю (нет смысла на самом деле, xPath — победил везде), но все уперлось именно в то, что некоторые из библиотек, перечисленных в конце статьи (в т.ч. Simple PHP DOM Parser) или умирают на больших деревьях или просто отказываются работать. На реальных проектах (где надо нечто большее, чем просто выбрать все ссылки на странице), я настоятельно рекомендую связку curl -> tidy -> xPath

Единственный минус xPath — очень капризен к DOM, зато есть встроенные отладчики чего и где угодно, куча готового кода на этих ваших гитах и т.д.
Да, xpath рулит, бесспорно. Просто здесь сама идея селекторов и текучий интерфейс показались заманчивыми, а в результате оказалось, что библиотека имеет большое количество раздражающих недостатков.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории