Как вы анализируете и обрабатываете HTML / XML в PHP?

Ответы:

1897

Собственные XML-расширения

Я предпочитаю использовать одно из собственных расширений XML, поскольку они поставляются в комплекте с PHP, обычно работают быстрее всех сторонних библиотек и дают мне полный контроль над разметкой.

DOM

Расширение DOM позволяет вам работать с документами XML через API DOM с PHP 5. Это реализация объектной модели документов W3C Core Level 3, независимого от платформы и языка интерфейса, который позволяет программам и сценариям динамически получать доступ и обновлять содержание, структура и стиль документов.

DOM способен анализировать и изменять (неработающий) HTML реального мира и выполнять запросы XPath . Он основан на libxml .

Требуется некоторое время, чтобы стать продуктивным с DOM, но это время того стоит IMO. Поскольку DOM является независимым от языка интерфейсом, вы найдете реализации на многих языках, поэтому, если вам нужно изменить язык программирования, скорее всего, вы уже знаете, как использовать API DOM этого языка.

Базовый пример использования можно найти в Grabbing атрибут href элемента A, а общий концептуальный обзор можно найти в DOMDocument на php

Как использовать расширение DOM широко освещалось в StackOverflow , поэтому, если вы решите его использовать, вы можете быть уверены, что большинство проблем, с которыми вы столкнулись, могут быть решены с помощью поиска / просмотра Переполнения стека.

XMLReader

Расширение XMLReader - это синтаксический анализатор XML. Читатель действует как курсор, идущий вперед по потоку документов и останавливающийся на каждом узле в пути.

XMLReader, как и DOM, основан на libxml. Я не знаю, как вызвать модуль HTML Parser, так что скорее всего, использование XMLReader для анализа неработающего HTML может быть менее надежным, чем использование DOM, где вы можете явно указать ему использовать модуль синтаксического анализа HTML libxml.

Базовый пример использования можно найти при получении всех значений из тегов h1 с использованием php

XML Parser

Это расширение позволяет создавать анализаторы XML, а затем определять обработчики для различных событий XML. Каждый анализатор XML также имеет несколько параметров, которые вы можете настроить.

Библиотека XML Parser также основана на libxml и реализует push-анализатор XML в стиле SAX . Это может быть лучшим выбором для управления памятью, чем DOM или SimpleXML, но с ним будет сложнее работать, чем парсером, реализованным XMLReader.

SimpleXml

Расширение SimpleXML предоставляет очень простой и легко используемый набор инструментов для преобразования XML в объект, который может обрабатываться с помощью обычных селекторов свойств и итераторов массива.

SimpleXML - это вариант, когда вы знаете, что HTML является верным XHTML. Если вам нужно разобрать битый HTML, даже не рассматривайте SimpleXml, потому что он захлебнется.

Базовый пример использования можно найти в разделе Простая программа для узла CRUD и значения узла файла XML, а в руководстве по PHP есть множество дополнительных примеров .


Сторонние библиотеки (на основе libxml)

Если вы предпочитаете использовать стороннюю библиотеку, я бы предложил использовать библиотеку, которая на самом деле использует DOM / libxml, а не разбор строки.

FluentDom - Репо

FluentDOM предоставляет jQuery-подобный свободный XML-интерфейс для DOMDocument в PHP. Селекторы пишутся в XPath или CSS (используя конвертер CSS в XPath). Текущие версии расширяют DOM, реализуя стандартные интерфейсы, и добавляют функции из DOM Living Standard. FluentDOM может загружать форматы, такие как JSON, CSV, JsonML, RabbitFish и другие. Может быть установлен через Composer.

HtmlPageDom

Wa72 \ HtmlPageDom` - это библиотека PHP для простого манипулирования HTML-документами. Для обхода дерева DOM требуется DomCrawler из компонентов Symfony2 и расширяет его, добавляя методы для манипулирования деревом DOM HTML-документов.

phpQuery (не обновляется годами)

phpQuery - это цепочечный API-интерфейс на основе объектной модели документов (DOM), управляемый селектором на стороне сервера, основанный на jQuery JavaScript Library, написанный на PHP5, и обеспечивающий дополнительный интерфейс командной строки (CLI).

Также смотрите: https://github.com/electrolinux/phpquery

Zend_Dom

Zend_Dom предоставляет инструменты для работы с документами и структурами DOM. В настоящее время мы предлагаем Zend_Dom_Query, который предоставляет унифицированный интерфейс для запросов к документам DOM с использованием селекторов XPath и CSS.

QueryPath

QueryPath - это библиотека PHP для управления XML и HTML. Он предназначен для работы не только с локальными файлами, но и с веб-службами и ресурсами базы данных. Он реализует большую часть интерфейса jQuery (включая селекторы в стиле CSS), но он сильно настроен для использования на стороне сервера. Может быть установлен через Composer.

fDOMDocument

fDOMDocument расширяет стандартную модель DOM для использования во всех случаях ошибок вместо предупреждений или уведомлений PHP. Они также добавляют различные пользовательские методы и ярлыки для удобства и упрощения использования DOM.

сабля / XML

Sabre / xml - это библиотека, которая упаковывает и расширяет классы XMLReader и XMLWriter для создания простой системы отображения «xml to object / array» и шаблона проектирования. Написание и чтение XML является однопроходным, поэтому может быть быстрым и требовать мало памяти для больших XML-файлов.

FluidXML

FluidXML - это PHP-библиотека для управления XML с помощью лаконичного и свободного API. Он использует XPath и гибкий шаблон программирования, чтобы быть веселым и эффективным.


Сторонний (не на основе libxml)

Преимущество использования DOM / libxml состоит в том, что вы получаете хорошую производительность из коробки, потому что вы основаны на собственном расширении. Однако не все сторонние библиотеки идут по этому пути. Некоторые из них перечислены ниже

PHP Простой HTML DOM Parser

  • Анализатор HTML DOM, написанный на PHP5 +, позволяет очень просто управлять HTML!
  • Требуется PHP 5+.
  • Поддерживает неверный HTML.
  • Найти теги на странице HTML с селекторами, как jQuery.
  • Извлечение содержимого из HTML в одну строку.

Я вообще не рекомендую этот парсер. Кодовая база ужасна, а сам парсер довольно медленный и требует много памяти. Не все селекторы jQuery (такие как дочерние селекторы ) возможны. Любая из библиотек на основе libxml должна легко превзойти это.

PHP Html Parser

PHPHtmlParser - это простой, гибкий анализатор HTML, который позволяет вам выбирать теги с помощью любого селектора CSS, например, jQuery. Цель состоит в том, чтобы помочь в разработке инструментов, которые требуют быстрого и простого способа просмотреть html, независимо от того, действителен он или нет! Этот проект изначально поддерживался sunra / php-simple-html-dom-parser, но поддержка, похоже, прекратилась, так что этот проект - моя адаптация его предыдущей работы.

Опять же, я бы не рекомендовал этот парсер. Это довольно медленно с высокой загрузкой процессора. Также нет функции очистки памяти созданных объектов DOM. Эти проблемы особенно характерны для вложенных циклов. Сама документация является неточной и написанной с ошибками, без ответов на исправления с 14 апреля 16.

Ganon

  • Универсальный токенизатор и HTML / XML / RSS DOM Parser
    • Возможность манипулировать элементами и их атрибутами
    • Поддерживает неверный HTML и UTF8
  • Может выполнять расширенные CSS3-подобные запросы к элементам (например, jQuery - поддерживаются пространства имен)
  • HTML beautifier (как HTML Tidy)
    • Сократить CSS и Javascript
    • Сортировка атрибутов, изменение регистра символов, корректный отступ и т. Д.
  • растяжимый
    • Разбор документов с использованием обратных вызовов на основе текущего символа / токена
    • Операции разделены на меньшие функции для легкого переопределения
  • Быстро и легко

Никогда не использовал это. Не могу сказать, хорошо ли это.


HTML 5

Вы можете использовать вышеупомянутое для разбора HTML5, но могут быть причуды из-за разметки, которую позволяет HTML5. Так что для HTML5 вы хотите рассмотреть возможность использования выделенного парсера, как

html5lib

Реализации Python и PHP HTML-парсера на основе спецификации WHATWG HTML5 для максимальной совместимости с основными настольными веб-браузерами.

Мы можем увидеть больше выделенных парсеров после завершения HTML5. Существует также блог от W3 под названием How-To для разбора html 5, который стоит проверить.


WebServices

Если вам не нравится программировать на PHP, вы также можете использовать веб-сервисы. В общем, я нашел очень мало полезности для них, но это только я и мои варианты использования.

ScraperWiki .

Внешний интерфейс ScraperWiki позволяет извлекать данные в той форме, которую вы хотите использовать в Интернете или в своих собственных приложениях. Вы также можете извлечь информацию о состоянии любого скребка.


Регулярные выражения

Последнее и наименее рекомендуемое , вы можете извлекать данные из HTML с помощью регулярных выражений . В целом, использование регулярных выражений в HTML не рекомендуется.

Большинство фрагментов, которые вы найдете в Интернете для соответствия разметке, являются хрупкими. В большинстве случаев они работают только для очень конкретного фрагмента HTML. Крошечные изменения разметки, такие как добавление пробелов где-либо, добавление или изменение атрибутов в теге, могут привести к сбою RegEx, если он написан неправильно. Вы должны знать, что вы делаете, прежде чем использовать RegEx на HTML.

HTML-парсеры уже знают синтаксические правила HTML. Регулярные выражения должны преподаваться для каждого нового RegEx, который вы пишете. RegEx хороши в некоторых случаях, но это действительно зависит от вашего варианта использования.

Вы можете написать более надежные парсеры , но написание полноценного и надежного пользовательского парсера с регулярными выражениями - пустая трата времени, когда вышеупомянутые библиотеки уже существуют и справляются с этим гораздо лучше.

Также см. Разбор HTML Путь Ктулху


книги

Если вы хотите потратить немного денег, посмотрите на

Я не связан с PHP Architect или авторами.

Гордон
источник
10
@ Нужно, что зависит от ваших потребностей. Мне не нужны запросы CSS Selector, поэтому я использую DOM исключительно с XPath. phpQuery стремится быть портом jQuery. Zend_Dom легкий. Вы действительно должны проверить их, чтобы увидеть, какой из них вам больше нравится.
Гордон
2
@ Ms2ger В основном, но не полностью. Как уже указывалось выше, вы можете использовать парсеры на основе libxml, но есть особые случаи, когда они будут задыхаться. Если вам нужна максимальная совместимость, вам лучше использовать специальный парсер. Я предпочитаю сохранить различие.
Гордон
9
Ваша точка зрения, что вы не используете PHP Simple HTML DOM Parser, кажется спорным.
Петах
3
По состоянию на 29 марта 2012 г. DOM не поддерживает html5, XMLReader не поддерживает HTML, и последняя фиксация html5lib для PHP произошла в сентябре 2009 г. Что использовать для анализа HTML5, HTML4 и XHTML?
Шиплу Мокаддим
4
@Nasha Я сознательно исключил печально известную напыщенную речь Zalgo из списка выше, потому что он не слишком полезен сам по себе и приводит к некоторому грузовому культу, так как это было написано. Людей связывали этой связью, независимо от того, насколько подходящим было бы регулярное выражение в качестве решения. Для более сбалансированного мнения, пожалуйста , см ссылку я сделал включить вместо этого и пройти через комментарии в stackoverflow.com/questions/4245008/...
Gordon
322

Попробуйте простой HTML DOM Parser

  • Анализатор HTML DOM, написанный на PHP 5+, который позволяет вам очень просто управлять HTML!
  • Требуется PHP 5+.
  • Поддерживает неверный HTML.
  • Найти теги на странице HTML с селекторами, как jQuery.
  • Извлечение содержимого из HTML в одну строку.
  • Скачать


Примеры:

Как получить элементы HTML:

// Create DOM from URL or file
$html = file_get_html('http://www.example.com/');

// Find all images
foreach($html->find('img') as $element)
       echo $element->src . '<br>';

// Find all links
foreach($html->find('a') as $element)
       echo $element->href . '<br>';


Как изменить элементы HTML:

// Create DOM from string
$html = str_get_html('<div id="hello">Hello</div><div id="world">World</div>');

$html->find('div', 1)->class = 'bar';

$html->find('div[id=hello]', 0)->innertext = 'foo';

echo $html;


Извлечь содержимое из HTML:

// Dump contents (without tags) from HTML
echo file_get_html('http://www.google.com/')->plaintext;


Соскоб Slashdot:

// Create DOM from URL
$html = file_get_html('http://slashdot.org/');

// Find all article blocks
foreach($html->find('div.article') as $article) {
    $item['title']     = $article->find('div.title', 0)->plaintext;
    $item['intro']    = $article->find('div.intro', 0)->plaintext;
    $item['details'] = $article->find('div.details', 0)->plaintext;
    $articles[] = $item;
}

print_r($articles);
Навид
источник
8
Ну, во-первых, есть вещи, которые мне нужно подготовить, такие как плохие DOM, код Invlid, а также анализ js с помощью механизма DNSBL, это также будет использоваться для поиска вредоносных сайтов / контента, также как я построил свой сайт на основе фреймворка. Он должен быть чистым, читаемым и хорошо структурированным. SimpleDim великолепен, но код немного грязный
RobertPitt
9
@ Роберт, вы также можете проверить htmlpurifier.org на предмет безопасности.
Гордон
3
У него есть одно верное замечание: simpleHTMLDOM трудно расширить, если вы не используете шаблон декоратора, который я считаю громоздким. Я содрогнулся, просто внося изменения в базовый класс (ы).
Эрик
1
Что я сделал, так это прогнал мой html через tidy перед отправкой в ​​SimpleDOM.
MB34
1
Я использую это в настоящее время, запускаю его как часть проекта для обработки нескольких сотен URL. Это становится очень медленным и регулярные таймауты сохраняются. Это отличный скрипт для начинающих, интуитивно простой в освоении, но слишком простой для более продвинутых проектов.
luke_mclachlan
236

Просто используйте DOMDocument-> loadHTML () и покончите с этим. Алгоритм синтаксического анализа HTML в libxml достаточно хорош и быстр, и, вопреки распространенному мнению, не подавляет искаженный HTML.

Эдвард З. Ян
источник
19
Правда. И он работает со встроенными в PHP классами XPath и XSLTProcessor, которые отлично подходят для извлечения контента.
Корнел
8
Для действительно искаженного HTML вы всегда можете запустить его через htmltidy, прежде чем передать его в DOM. Всякий раз, когда мне нужно почистить данные из HTML, я всегда использую DOM или, по крайней мере, simplexml.
Фрэнк Фармер
9
Еще одна вещь, связанная с загрузкой искаженного HTML-кода, заключается в том, что было бы разумно вызвать libxml_use_internal_errors (true), чтобы предотвратить предупреждения, которые прекратят анализ.
Хаски
6
Я использовал DOMDocument для анализа около 1000 HTML-источников (на разных языках, закодированных с различными кодировками) без каких-либо проблем. Вы можете столкнуться с проблемами кодирования с этим, но они не являются непреодолимыми. Вам нужно знать 3 вещи: 1) loadHTML использует набор символов мета-тега для определения кодировки 2) # 2 может привести к неправильному обнаружению кодировки, если html-контент не содержит эту информацию 3) плохие символы UTF-8 могут отключить анализатор. В таких случаях используйте комбинацию mb_detect_encoding () и Simplepie RSS Parser для кодирования / преобразования / удаления плохих символов UTF-8 для обходных путей.
Ноль
1
DOM действительно поддерживает XPath, взгляните на DOMXPath .
Райан МакКью
147

Почему вы не должны и когда вы должны использовать регулярные выражения?

Во-первых, распространенное заблуждение: регулярные выражения не предназначены для « разбора » HTML. Однако регулярные выражения могут « извлечь » данные. Извлечение - это то, для чего они созданы. Основным недостатком регулярного извлечения HTML-кода над надлежащими наборами инструментов SGML или базовыми синтаксическими анализаторами XML являются их синтаксические усилия и разная надежность.

Учтите, что создание надежного регулярного выражения для извлечения HTML:

<a\s+class="?playbutton\d?[^>]+id="(\d+)".+?    <a\s+class="[\w\s]*title
[\w\s]*"[^>]+href="(http://[^">]+)"[^>]*>([^<>]+)</a>.+?

является менее читабельным, чем простой эквивалент phpQuery или QueryPath:

$div->find(".stationcool a")->attr("title");

Однако существуют конкретные случаи использования, в которых они могут помочь.

  • Многие внешние интерфейсы DOM не отображают HTML-комментарии <!--, которые, тем не менее, иногда являются более полезными якорями для извлечения. В частности, вариации псевдо-HTML <$var>или остатки SGML легко укротить с помощью регулярных выражений.
  • Часто регулярные выражения могут сохранить пост-обработку. Однако сущности HTML часто требуют ручной заботы.
  • И, наконец, для чрезвычайно простых задач, таких как извлечение <img src = urls, они на самом деле являются вероятным инструментом. Преимущество в скорости по сравнению с синтаксическими анализаторами SGML / XML в основном проявляется в этих базовых процедурах извлечения.

Иногда даже рекомендуется предварительно извлечь фрагмент HTML с помощью регулярных выражений /<!--CONTENT-->(.+?)<!--END-->/и обработать остаток с помощью более простых внешних интерфейсов анализатора HTML.

Примечание: у меня действительно есть это приложение , где я использую разбор XML и регулярные выражения в качестве альтернативы. Буквально на прошлой неделе перестал разбираться PyQuery, и регулярное выражение все еще работало. Да, странно, и я не могу объяснить это сам. Но так случилось.
Поэтому, пожалуйста, не отказывайтесь от реальных соображений, просто потому, что они не соответствуют регулярному выражению = злой мем. Но давайте также не будем голосовать слишком много. Это просто sidenote для этой темы.

марио
источник
20
DOMCommentМожно читать комментарии, поэтому нет причин использовать Regex для этого.
Гордон
4
Ни инструментарий SGML, ни парсеры XML не подходят для анализа реального мира HTML. Для этого подходит только специальный HTML-парсер.
Alohci
12
@Alohci DOMиспользует libxml, а libxml имеет отдельный модуль синтаксического анализа HTML, который будет использоваться при загрузке HTML, loadHTML()чтобы он мог очень сильно загружать «реальный» (читай неработающий) HTML.
Гордон
6
Ну, просто комментарий о вашей точке зрения "реального мира". Конечно, есть полезные ситуации для Regex при разборе HTML. И есть также полезные ситуации для использования GOTO. И есть полезные ситуации для переменных-переменных. Таким образом, ни одна конкретная реализация не может полностью использовать его. Но это ОЧЕНЬ сильный предупреждающий знак. И среднестатистический разработчик вряд ли будет достаточно детализирован, чтобы заметить разницу. Так что, как правило, Regex GOTO и Variable-Variables являются злом. Есть не злые применения, но это исключения (и редкие в этом отношении) ... (ИМХО)
ircmaxell
11
@mario: На самом деле, HTML можно «правильно» проанализировать с помощью регулярных выражений, хотя обычно требуется несколько из них, чтобы справиться с работой. Это просто королевская боль в общем случае. В конкретных случаях с четко определенным вводом он граничит с тривиальным. Это те случаи, когда люди должны использовать регулярные выражения. Большие старые голодные тяжелые парсеры - действительно то, что вам нужно для общих случаев, хотя обычному пользователю не всегда понятно, где провести эту линию. Какой бы код проще и проще, побеждает.
tchrist
131

phpQuery и QueryPath чрезвычайно похожи в репликации свободно распространяемого API jQuery. Именно поэтому они являются двумя из самых простых подходов для правильного анализа HTML в PHP.

Примеры для QueryPath

По сути, вы сначала создаете запрашиваемое дерево DOM из строки HTML:

 $qp = qp("<html><body><h1>title</h1>..."); // or give filename or URL

Полученный объект содержит полное представление дерева документа HTML. Его можно пройти, используя методы DOM. Но общий подход заключается в использовании CSS-селекторов, как в jQuery:

 $qp->find("div.classname")->children()->...;

 foreach ($qp->find("p img") as $img) {
     print qp($img)->attr("src");
 }

В основном вы хотите использовать простые #idи .classили DIVтеги селекторов для ->find(). Но вы также можете использовать операторы XPath , которые иногда работают быстрее. Также типичные методы jQuery, такие как ->children()и ->text()особенно ->attr()упрощающие извлечение правильных фрагментов HTML. (И уже имеют свои объекты SGML, декодированные.)

 $qp->xpath("//div/p[1]");  // get first paragraph in a div

QueryPath также позволяет вставлять новые теги в stream ( ->append), а затем выводить и предварительно обновлять обновленный документ ( ->writeHTML). Он может не только анализировать искаженный HTML, но также различные XML-диалекты (с пространствами имен) и даже извлекать данные из микроформатов HTML (XFN, vCard).

 $qp->find("a[target=_blank]")->toggleClass("usability-blunder");

,

phpQuery или QueryPath?

Обычно QueryPath лучше подходит для манипулирования документами. Хотя phpQuery также реализует некоторые псевдо-AJAX-методы (только HTTP-запросы), чтобы больше походить на jQuery. Говорят, что phpQuery часто быстрее, чем QueryPath (из-за меньшего количества общих функций).

Для получения дополнительной информации о различиях см. Это сравнение на машине обратного хода от tagbyte.org . (Первоначальный источник пропал, так что вот ссылка на интернет-архив. Да, вы все еще можете найти пропущенные страницы, люди.)

А вот и полное введение в QueryPath .

преимущества

  • Простота и надежность
  • Простые в использовании альтернативы ->find("a img, a object, div a")
  • Правильное удаление данных (по сравнению с регулярными выражениями)
марио
источник
88

Simple HTML DOM - отличный анализатор с открытым исходным кодом:

simplehtmldom.sourceforge

Он обрабатывает элементы DOM объектно-ориентированным способом, и новая итерация имеет большой охват для несовместимого кода. Есть также несколько замечательных функций, которые вы могли бы видеть в JavaScript, например, функция «find», которая будет возвращать все экземпляры элементов этого имени тега.

Я использовал это во многих инструментах, тестируя на многих различных типах веб-страниц, и я думаю, что это прекрасно работает.

Роберт Элвелл
источник
61

Один общий подход, о котором я не упомянул, это запуск HTML через Tidy. , который можно настроить так, чтобы он выдавал гарантированно-действительный XHTML. Тогда вы можете использовать любую старую библиотеку XML.

Но в зависимости от вашей конкретной проблемы вы должны взглянуть на этот проект: http://fivefilters.org/content-only/ - это модифицированная версия алгоритма Readability , который предназначен для извлечения только текстового содержимого (не заголовков) и нижние колонтитулы) со страницы.

Eli
источник
56

За 1а и 2: я бы проголосовал за новый класс компонентов Symfony DOMCrawler ( DomCrawler ). Этот класс позволяет выполнять запросы, аналогичные селекторам CSS. Взгляните на эту презентацию для примеров из реального мира: news-of-the-symfony2-world .

Компонент предназначен для автономной работы и может использоваться без Symfony.

Единственным недостатком является то, что он будет работать только с PHP 5.3 или новее.

Тимо
источник
jquery-подобные css-запросы хорошо известны, потому что есть некоторые вещи, которые отсутствуют в документации по w3c, но присутствуют как дополнительные функции в jquery.
Никола Петкански
53

Кстати, это обычно называется скребком экрана . Для этого я использовал библиотеку Simple HTML Dom Parser .

Джоэл Верхаген
источник
8
Не совсем верно ( en.wikipedia.org/wiki/Screen_scraping#Screen_scraping ). Ключ находится в «экране»; в описанном случае экран не задействован. Хотя, по общему признанию, термин перенес очень много недавних злоупотреблений.
Бобби Джек
4
Я не проверяю, содержимое, которое будет проанализировано, будет разрешено поставщиком содержимого в соответствии с моим соглашением.
Роберт Питт
41

Мы создали довольно много сканеров для наших нужд. В конце концов, лучше всего использовать простые регулярные выражения. Несмотря на то, что перечисленные выше библиотеки хороши по той причине, что они созданы, если вы знаете, что ищете, регулярные выражения - более безопасный путь, поскольку вы можете обрабатывать также недопустимые структуры HTML / XHTML , которые потерпят неудачу при загрузке через большинство парсеров.

jancha
источник
38

Я рекомендую PHP Simple HTML DOM Parser .

Это действительно имеет приятные функции, такие как:

foreach($html->find('img') as $element)
       echo $element->src . '<br>';
Greg
источник
36

Это звучит как хорошее описание задачи технологии W3C XPath . Легко выражать запросы типа «вернуть все hrefатрибуты в imgтегах, которые вложены <foo><bar><baz> elements». Не будучи фанатом PHP, я не могу сказать вам, в какой форме XPath может быть доступен. Если вы можете вызвать внешнюю программу для обработки HTML-файла, вы сможете использовать версию XPath для командной строки. Для быстрого ознакомления см. Http://en.wikipedia.org/wiki/XPath .

Jens
источник
29

Сторонние альтернативы SimpleHtmlDom, использующие DOM вместо анализа строк: phpQuery , Zend_Dom , QueryPath и FluentDom .

Amal Murali
источник
3
Если вы уже скопировали мои комментарии, по крайней мере, связывайте их должным образом;) Это должно быть: Предлагаемые сторонние альтернативы SimpleHtmlDom, которые фактически используют DOM вместо анализа строк: phpQuery , Zend_Dom , QueryPath и FluentDom .
Гордон
1
Хорошие ответы - отличный источник. stackoverflow.com/questions/3606792/…
danidacar
24

Да, вы можете использовать simple_html_dom для этой цели. Тем не менее, я довольно много работал с simple_html_dom, особенно для удаления из Интернета, и обнаружил, что он слишком уязвим. Это делает основную работу, но я не буду рекомендовать это так или иначе.

Я никогда не использовал curl для этой цели, но я узнал, что curl может выполнять эту работу гораздо эффективнее и гораздо надежнее.

Пожалуйста, проверьте эту ссылку: scraping-sites-with-curl

Rafay
источник
2
curl может получить файл, но он не будет анализировать HTML для вас. Это сложная часть.
cHao
23

QueryPath хорош, но будьте осторожны с «состоянием отслеживания», потому что если вы не понимаете, что это значит, это может означать, что вы тратите много времени на отладку, пытаясь выяснить, что произошло и почему код не работает.

Это означает, что каждый вызов в наборе результатов изменяет набор результатов в объекте, он не является цепным, как в jquery, где каждая ссылка является новым набором, у вас есть один набор, который является результатом вашего запроса, и каждый вызов функции изменяет этот единственный набор.

чтобы получить jquery-подобное поведение, вам нужно выполнить ветвление, прежде чем выполнять операцию, подобную фильтрующему / модифицирующему, это означает, что она будет более точно отражать то, что происходит в jquery.

$results = qp("div p");
$forename = $results->find("input[name='forename']");

$resultsтеперь содержит результирующий набор для input[name='forename']НЕ исходного запроса, "div p"это меня сильно смутило , я обнаружил, что QueryPath отслеживает фильтры и находит и все, что изменяет ваши результаты и сохраняет их в объекте. вам нужно сделать это вместо

$forename = $results->branch()->find("input[name='forname']")

тогда $resultsон не будет изменен, и вы сможете снова и снова использовать результирующий набор, возможно, кто-то, обладающий гораздо большими знаниями, может немного прояснить ситуацию, но в основном это похоже на то, что я нашел.

Кристофер Томас
источник
20

Advanced Html Dom - это простая замена HTML DOM , предлагающая тот же интерфейс, но основанный на DOM, что означает отсутствие проблем с памятью.

Он также имеет полную поддержку CSS, включая расширения jQuery .

pguardiario
источник
Я получил хорошие результаты от Advanced Html Dom, и я думаю, что он должен быть в списке в принятом ответе. Однако важно знать, что для любого, кто полагается на его «Цель этого проекта - стать заменой на основе DOM простой библиотеки PHP html dom ... Если вы используете файл / str_get_html, то вам не нужно изменить что-нибудь. " archive.is/QtSuj#selection-933.34-933.100 заключается в том, что вам может потребоваться внести изменения в код для устранения некоторых несовместимостей. Я отметил четыре известных мне в проблемах проекта github. github.com/monkeysuffrage/advanced_html_dom/issues
ChrisJJ
Работал ! Слава
Фейсал Шани
18

Для HTML5 библиотека html5 была заброшена в течение многих лет. Единственная библиотека HTML5, которую я могу найти с недавними обновлениями и записями об обслуживании, - это html5-php, который только что был переведен в бета-версию 1.0 чуть более недели назад.

Рейд Джонсон
источник
17

Я написал анализатор XML общего назначения, который может легко обрабатывать файлы GB. Он основан на XMLReader и очень прост в использовании:

$source = new XmlExtractor("path/to/tag", "/path/to/file.xml");
foreach ($source as $tag) {
    echo $tag->field1;
    echo $tag->field2->subfield1;
}

Вот репозиторий Github : XmlExtractor

Пол Варелис
источник
17

Я создал библиотеку с именем PHPPowertools / DOM-Query , которая позволяет сканировать документы HTML5 и XML так же, как вы делаете это с jQuery.

Под капотом он использует symfony / DomCrawler для преобразования селекторов CSS в селекторы XPath . Он всегда использует один и тот же DomDocument, даже при передаче одного объекта другому, чтобы обеспечить достойную производительность.


Пример использования:

namespace PowerTools;

// Get file content
$htmlcode = file_get_contents('https://github.com');

// Define your DOMCrawler based on file string
$H = new DOM_Query($htmlcode);

// Define your DOMCrawler based on an existing DOM_Query instance
$H = new DOM_Query($H->select('body'));

// Passing a string (CSS selector)
$s = $H->select('div.foo');

// Passing an element object (DOM Element)
$s = $H->select($documentBody);

// Passing a DOM Query object
$s = $H->select( $H->select('p + p'));

// Select the body tag
$body = $H->select('body');

// Combine different classes as one selector to get all site blocks
$siteblocks = $body->select('.site-header, .masthead, .site-body, .site-footer');

// Nest your methods just like you would with jQuery
$siteblocks->select('button')->add('span')->addClass('icon icon-printer');

// Use a lambda function to set the text of all site blocks
$siteblocks->text(function( $i, $val) {
    return $i . " - " . $val->attr('class');
});

// Append the following HTML to all site blocks
$siteblocks->append('<div class="site-center"></div>');

// Use a descendant selector to select the site's footer
$sitefooter = $body->select('.site-footer > .site-center');

// Set some attributes for the site's footer
$sitefooter->attr(array('id' => 'aweeesome', 'data-val' => 'see'));

// Use a lambda function to set the attributes of all site blocks
$siteblocks->attr('data-val', function( $i, $val) {
    return $i . " - " . $val->attr('class') . " - photo by Kelly Clark";
});

// Select the parent of the site's footer
$sitefooterparent = $sitefooter->parent();

// Remove the class of all i-tags within the site's footer's parent
$sitefooterparent->select('i')->removeAttr('class');

// Wrap the site's footer within two nex selectors
$sitefooter->wrap('<section><div class="footer-wrapper"></div></section>');

[...]

Поддерживаемые методы:


  1. Переименован в «выбрать» по понятным причинам
  2. Переименован в «void», так как «пустой» является зарезервированным словом в PHP

НОТА :

Библиотека также включает собственный автозагрузчик нулевой конфигурации для PSR-0-совместимых библиотек. Приведенный пример должен работать из коробки без какой-либо дополнительной настройки. Кроме того, вы можете использовать его с композитором.

Джон Слегерс
источник
Похоже, правильный инструмент для работы, но не загружается для меня в PHP 5.6.23 в Worpress. Любые дополнительные указания о том, как правильно его включить? Включено с: define ("BASE_PATH", dirname ( FILE )); define ("LIBRARY_PATH", BASE_PATH. DIRECTORY_SEPARATOR. 'lib / vendor'); требуют LIBRARY_PATH. DIRECTORY_SEPARATOR. 'Loader.php'; Loader :: init (массив (LIBRARY_PATH, USER_PATH)); в functions.php
lithiumlab
15

Вы можете попробовать использовать что-то вроде HTML Tidy для очистки любого «сломанного» HTML и преобразования HTML в XHTML, который затем можно проанализировать с помощью синтаксического анализатора XML.

CesarB
источник
15

Другой вариант, который вы можете попробовать - это QueryPath . Он вдохновлен jQuery, но на сервере в PHP и используется в Drupal .

Ric
источник
12

XML_HTMLSaxдовольно стабилен - даже если он больше не поддерживается. Другой вариант может состоять в том, чтобы передать вам HTML через HTML Tidy, а затем проанализировать его с помощью стандартных инструментов XML.

troelskn
источник
11

Платформа Symfony имеет пакеты, которые могут анализировать HTML, и вы можете использовать стиль CSS для выбора DOM вместо использования XPath .

Туонг Ле
источник
11

Есть много способов обработки HTML / XML DOM, большинство из которых уже были упомянуты. Следовательно, я не буду пытаться перечислить их сам.

Я просто хочу добавить, что лично я предпочитаю использовать расширение DOM и почему:

  • iit оптимально использует преимущество в производительности базового кода C
  • это OO PHP (и позволяет мне его подкласс)
  • это довольно низкий уровень (что позволяет мне использовать его как не раздутую основу для более продвинутого поведения)
  • он обеспечивает доступ ко всем частям DOM (в отличие, например, от SimpleXml, который игнорирует некоторые из менее известных функций XML)
  • у него есть синтаксис, используемый для сканирования DOM, который похож на синтаксис, используемый в нативном Javascript.

И хотя мне не хватает возможности использовать селекторы CSS для DOMDocument, есть довольно простой и удобный способ добавить эту функцию: создание подклассов DOMDocumentи добавление JS-подобныхquerySelectorAll и querySelectorметодов к вашему подклассу.

Для анализа селекторов я рекомендую использовать очень минималистичный компонент CssSelector из среды Symfony. . Этот компонент просто переводит селекторы CSS в селекторы XPath, которые затем могут быть переданы в a DOMXpathдля получения соответствующего Nodelist.

Затем вы можете использовать этот (все еще очень низкоуровневый) подкласс в качестве основы для более высокоуровневых классов, например. анализировать очень специфические типы XML или добавлять более jQuery-подобное поведение.

Код ниже выходит прямо из моей библиотеки DOM-Query и использует описанную мной технику.

Для разбора HTML:

namespace PowerTools;

use \Symfony\Component\CssSelector\CssSelector as CssSelector;

class DOM_Document extends \DOMDocument {
    public function __construct($data = false, $doctype = 'html', $encoding = 'UTF-8', $version = '1.0') {
        parent::__construct($version, $encoding);
        if ($doctype && $doctype === 'html') {
            @$this->loadHTML($data);
        } else {
            @$this->loadXML($data);
        }
    }

    public function querySelectorAll($selector, $contextnode = null) {
        if (isset($this->doctype->name) && $this->doctype->name == 'html') {
            CssSelector::enableHtmlExtension();
        } else {
            CssSelector::disableHtmlExtension();
        }
        $xpath = new \DOMXpath($this);
        return $xpath->query(CssSelector::toXPath($selector, 'descendant::'), $contextnode);
    }

    [...]

    public function loadHTMLFile($filename, $options = 0) {
        $this->loadHTML(file_get_contents($filename), $options);
    }

    public function loadHTML($source, $options = 0) {
        if ($source && $source != '') {
            $data = trim($source);
            $html5 = new HTML5(array('targetDocument' => $this, 'disableHtmlNsInDom' => true));
            $data_start = mb_substr($data, 0, 10);
            if (strpos($data_start, '<!DOCTYPE ') === 0 || strpos($data_start, '<html>') === 0) {
                $html5->loadHTML($data);
            } else {
                @$this->loadHTML('<!DOCTYPE html><html><head><meta charset="' . $encoding . '" /></head><body></body></html>');
                $t = $html5->loadHTMLFragment($data);
                $docbody = $this->getElementsByTagName('body')->item(0);
                while ($t->hasChildNodes()) {
                    $docbody->appendChild($t->firstChild);
                }
            }
        }
    }

    [...]
}

См. Также Анализ документов XML с помощью селекторов CSS , создатель Symfony Фабьен Потенциер (Fabien Potencier) о его решении создать компонент CssSelector для Symfony и способы его использования.

Джон Слегерс
источник
9

С FluidXML вы можете запрашивать и выполнять итерацию XML, используя XPath и CSS Selector .

$doc = fluidxml('<html>...</html>');

$title = $doc->query('//head/title')[0]->nodeValue;

$doc->query('//body/p', 'div.active', '#bgId')
        ->each(function($i, $node) {
            // $node is a DOMNode.
            $tag   = $node->nodeName;
            $text  = $node->nodeValue;
            $class = $node->getAttribute('class');
        });

https://github.com/servo-php/fluidxml

Daniele Orlando
источник
7

JSON и массив из XML в три строки:

$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);

Та да!

Антонио Макс
источник
7

Есть несколько причин не разбирать HTML с помощью регулярных выражений. Но если у вас есть полный контроль над тем, что будет генерироваться HTML, то вы можете сделать это с помощью простого регулярного выражения.

Выше это функция, которая анализирует HTML по регулярному выражению. Обратите внимание, что эта функция очень чувствительна и требует соблюдения HTML определенных правил, но во многих сценариях она работает очень хорошо. Если вы хотите простой парсер и не хотите устанавливать библиотеки, попробуйте:

function array_combine_($keys, $values) {
    $result = array();
    foreach ($keys as $i => $k) {
        $result[$k][] = $values[$i];
    }
    array_walk($result, create_function('&$v', '$v = (count($v) == 1)? array_pop($v): $v;'));

    return $result;
}

function extract_data($str) {
    return (is_array($str))
        ? array_map('extract_data', $str)
        : ((!preg_match_all('#<([A-Za-z0-9_]*)[^>]*>(.*?)</\1>#s', $str, $matches))
            ? $str
            : array_map(('extract_data'), array_combine_($matches[1], $matches[2])));
}

print_r(extract_data(file_get_contents("http://www.google.com/")));
Daniel Loureiro
источник
2

Я создал библиотеку под названием HTML5DOMDocument, которая свободно доступна по адресу https://github.com/ivopetkov/html5-dom-document-php.

Он также поддерживает селекторы запросов, которые, я думаю, будут чрезвычайно полезны в вашем случае. Вот пример кода:

$dom = new IvoPetkov\HTML5DOMDocument();
$dom->loadHTML('<!DOCTYPE html><html><body><h1>Hello</h1><div class="content">This is some text</div></body></html>');
echo $dom->querySelector('h1')->innerHTML;
Иво Петков
источник
0

Если вы знакомы с селектором jQuery, вы можете использовать ScarletsQuery для PHP

<pre><?php
include "ScarletsQuery.php";

// Load the HTML content and parse it
$html = file_get_contents('https://www.lipsum.com');
$dom = Scarlets\Library\MarkupLanguage::parseText($html);

// Select meta tag on the HTML header
$description = $dom->selector('head meta[name="description"]')[0];

// Get 'content' attribute value from meta tag
print_r($description->attr('content'));

$description = $dom->selector('#Content p');

// Get element array
print_r($description->view);

Эта библиотека обычно занимает менее 1 секунды для обработки офлайн html.
Он также принимает неверный HTML или пропущенную кавычку в атрибутах тега.

StefansArya
источник
0

Лучший метод для разбора xml:

$xml='http://www.example.com/rss.xml';
$rss = simplexml_load_string($xml);
$i = 0;
foreach ($rss->channel->item as $feedItem) {
  $i++;
  echo $title=$feedItem->title;
  echo '<br>';
  echo $link=$feedItem->link;
  echo '<br>';
  if($feedItem->description !='') {
    $des=$feedItem->description;
  } else {
    $des='';
  }
  echo $des;
  echo '<br>';
  if($i>5) break;
}
user8031209
источник