Как можно разобрать HTML / XML и извлечь из него информацию?
Как вы разбираете и обрабатываете HTML / XML в PHP?
Ответы (31)
Собственные расширения XML
Я предпочитаю использовать одно из собственных расширений XML, поскольку они поставляются в комплекте с PHP, обычно быстрее, чем все сторонние библиотеки, и дают мне весь необходимый контроль над разметкой.
DOM
Расширение DOM позволяет вам работать с XML-документами через DOM API с PHP 5. Это реализация W3C Document Object Model Core Level 3, интерфейс, не зависящий от платформы и языка, который позволяет программам и скриптам динамически доступ и обновление содержимого, структуры и стиля документов.
DOM может анализировать и изменять реальный (сломанный) HTML и выполнять запросы XPath. Он основан на libxml.
Чтобы стать продуктивным с DOM, нужно время, но оно того стоит, IMO. Поскольку DOM не зависит от языка интерфейса, вы найдете реализации на многих языках, поэтому, если вам нужно изменить язык программирования, скорее всего, вы уже будете знать, как использовать DOM API этого языка.
Базовый пример использования можно найти в Захват атрибута href элемента A и общий концептуальный обзор можно найти в DOMDocument в php
Как использовать расширение DOM подробно описано в StackOverflow, поэтому, если вы решите его использовать, вы можете быть уверены, что большинство проблем, с которыми вы столкнетесь, можно решить путем поиска / просмотра Stack Overflow.
XMLReader
Расширение XMLReader - это синтаксический анализатор XML. Считыватель действует как курсор, движущийся вперед по потоку документа и останавливающийся на каждом узле в пути.
XMLReader, как и DOM, основан на libxml. Я не знаю, как запустить модуль синтаксического анализа HTML, поэтому вероятность использования XMLReader для разбора сломанного HTML может быть менее надежной, чем использование DOM, где вы можете явно указать ему использовать модуль синтаксического анализа HTML libxml.
Базовый пример использования можно найти по адресу получение всех значений из тегов h1 с использованием php
Анализатор XML
Это расширение позволяет создавать синтаксические анализаторы XML, а затем определять обработчики для различных событий XML. У каждого анализатора XML также есть несколько параметров, которые вы можете настроить.
Библиотека синтаксического анализатора XML также основана на libxml и реализует синтаксический анализатор push XML в стиле SAX. Он может быть лучшим выбором для управления памятью, чем DOM или SimpleXML, но с ним будет труднее работать, чем с синтаксическим анализатором извлечения, реализованным XMLReader.
SimpleXml
Расширение SimpleXML предоставляет очень простой и удобный набор инструментов для преобразования XML в объект, который можно обрабатывать с помощью обычных селекторов свойств и итераторов массивов.
SimpleXML - это вариант, когда вы знаете, что HTML является допустимым XHTML. Если вам нужно разобрать битый HTML, даже не рассматривайте SimpleXml, потому что он задохнется.
Базовый пример использования можно найти по адресу Простая программа для узлов CRUD и значений узлов в xml-файле, а также множество дополнительных примеров в Руководстве по PHP.
Сторонние библиотеки (на основе libxml)
Если вы предпочитаете использовать стороннюю библиотеку, я бы предложил использовать библиотеку, которая фактически использует DOM / libxml внизу вместо синтаксического анализа строк.
FluentDom - Репо
FluentDOM предоставляет гибкий XML-интерфейс, подобный jQuery, для 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 и расширяет его, добавляя методы для управления Дерево DOM документов HTML.
phpQuery (не обновлялся годами)
phpQuery - это серверный API-интерфейс объектной модели документа (DOM), управляемый селектором CSS3, основанный на библиотеке jQuery JavaScript, написанной на 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.
sabre/xml
saber / xml - это библиотека, которая обертывает и расширяет классы XMLReader и XMLWriter для создания простой системы отображения «xml в объект / массив» и шаблона проектирования. Запись и чтение XML являются однопроходными и поэтому могут быть быстрыми и требовать небольшого объема памяти для больших файлов xml.
FluidXML
FluidXML - это библиотека PHP для управления XML с помощью краткого и понятного API. Он использует XPath и шаблон свободного программирования, чтобы сделать его увлекательным и эффективным.
Сторонние (не на основе libxml)
Преимущество построения на основе DOM / libxml заключается в том, что вы получаете хорошую производительность прямо из коробки, потому что вы основаны на собственном расширении. Однако не все сторонние библиотеки идут по этому пути. Некоторые из них перечислены ниже
PHP Simple 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 исправлений нет.
Ганон
- Универсальный токенизатор и парсер HTML / XML / RSS DOM
Ability to manipulate elements and their attributes
Supports invalid HTML and UTF8
Can perform advanced CSS3-like queries on elements (like jQuery -- namespaces supported)
- Инструмент для украшения HTML (например, HTML Tidy)
Minify CSS and Javascript
Sort attributes, change character case, correct indentation, etc.
- Расширяемый
Parsing documents using callbacks based on current character/token
Operations separated in smaller functions for easy overriding
- Быстро и просто
Никогда не использовал. Не могу сказать, хорошо ли это.
HTML 5
Вы можете использовать вышеуказанное для синтаксического анализа HTML5, но могут быть странности из-за разметки, допускаемой HTML5. Итак, для HTML5 вы хотите использовать специальный парсер, например
Реализации синтаксического анализатора HTML на Python и PHP на основе спецификации WHATWG HTML5 для максимальной совместимости с основными настольными веб-браузерами.
Мы можем увидеть больше специализированных парсеров, когда HTML5 будет завершен. Есть также сообщение в блоге W3 под названием How-To for html 5 parsing, которое стоит проверить.
Веб-службы
Если вы не хотите программировать PHP, вы также можете использовать веб-службы. В общем, я нашел для них очень мало полезности, но это только я и мои варианты использования.
ScraperWiki.
Внешний интерфейс ScraperWiki позволяет извлекать данные в желаемой форме для использования в сети или в собственных приложениях. Вы также можете извлечь информацию о состоянии любого скребка.
Регулярные выражения
Последний и наименее рекомендуемый , вы можете извлекать данные из HTML с помощью регулярных выражений. В целом использование регулярных выражений в HTML не рекомендуется.
Большинство фрагментов кода, которые вы найдете в Интернете для соответствия разметке, непрочны. В большинстве случаев они работают только с определенным фрагментом HTML. Небольшие изменения разметки, такие как добавление пробелов, добавление или изменение атрибутов в теге, могут привести к сбою RegEx, если он неправильно написан. Вы должны знать, что делаете, прежде чем использовать RegEx в HTML.
Анализаторы HTML уже знают синтаксические правила HTML. Регулярные выражения необходимо учить для каждого нового написанного вами регулярного выражения. В некоторых случаях RegEx подходят, но это действительно зависит от вашего варианта использования.
Вы можете писать более надежные парсеры, но написание полного и надежного настраиваемого парсера с регулярными выражениями - пустая трата времени, когда вышеупомянутые библиотеки уже существуют и работают намного лучше по этому.
См. Также Parsing Html The Cthulhu Way
Книги
Если вы хотите потратить немного денег, посмотрите
Я не связан с PHP Architect или авторами.
Есть много способов:
Общее:
-
Собственные расширения XML: они поставляются в комплекте с PHP, обычно быстрее, чем все сторонние библиотеки, и дают мне весь необходимый вам контроль над разметкой.
-
DOM: DOM может анализировать и изменять реальный (сломанный) HTML и выполнять запросы XPath. Он основан на libxml.
-
XML Reader: XMLReader, как и DOM, основан на libxml. Расширение XMLReader - это синтаксический анализатор XML. Считыватель действует как курсор, движущийся вперед по потоку документа и останавливающийся на каждом узле по пути
-
Анализатор XML: Это расширение позволяет создавать синтаксические анализаторы XML, а затем определять обработчики для различных событий XML. У каждого анализатора XML также есть несколько параметров, которые вы можете настроить. Он реализует парсер push XML в стиле SAX.
-
Простой XML: Расширение SimpleXML предоставляет очень простой и удобный в использовании набор инструментов для преобразования XML в объект, который можно обрабатывать с помощью обычных селекторов свойств и итераторов массивов.
Сторонние библиотеки [на основе libxml]:
-
FluentDom - Repo: FluentDOM предоставляет гибкий XML-интерфейс, подобный jQuery, для DOMDocument на PHP. Он может загружать такие форматы, как JSON, CSV, JsonML, RabbitFish и другие. Может быть установлен через Composer.
-
HtmlPageDom: - это библиотека PHP для простого управления HTML-документами с помощью компонентов. Требуется DomCrawler из компонентов Symfony2 для обхода дерева DOM и расширяет его, добавляя методы для управления деревом DOM документов HTML.
-
ZendDOM: Zend_Dom предоставляет инструменты для работы с документами и структурами DOM. В настоящее время они предлагают Zend_Dom_Query, который предоставляет унифицированный интерфейс для запросов к документам DOM с использованием селекторов XPath и CSS.
-
QueryPath: QueryPath - это библиотека PHP для управления XML и HTML. Он предназначен для работы не только с локальными файлами, но и с веб-службами и ресурсами баз данных. Он реализует большую часть интерфейса jQuery (включая селекторы в стиле CSS), но он сильно настроен для использования на стороне сервера. Может быть установлен через Composer.
-
Документ fDOM: fDOMDocument расширяет стандартную модель DOM для использования исключений во всех случаях ошибок вместо предупреждений или уведомлений PHP. Они также добавляют различные пользовательские методы и ярлыки для удобства и упрощения использования DOM.
-
Sabre / XML: saber / xml - это библиотека, которая объединяет и расширяет классы XMLReader и XMLWriter для создания простой системы отображения «xml в объект / массив» и шаблона проектирования. Запись и чтение XML являются однопроходными и поэтому могут быть быстрыми и требовать небольшого объема памяти для больших файлов xml.
-
FluidXML: FluidXML - это библиотека PHP для управления XML с помощью краткого и понятного API. Он использует XPath и шаблон свободного программирования, чтобы сделать его увлекательным и эффективным.
Сторонние библиотеки [не на основе libxml]:
-
PHP Simple HTML DOM Parser: Парсер HTML DOM, написанный на PHP5 +, позволяет очень легко манипулировать HTML, для этого требуется PHP 5+. Также поддерживает недопустимый HTML. Он извлекает содержимое из HTML в одну строку. Кодовая база ужасная и работает очень медленно.
-
PHP Html Parser: HPHtmlParser - это простой, гибкий анализатор HTML, который позволяет выбирать теги с помощью любого селектора CSS, например jQuery. Цель состоит в том, чтобы помочь в разработке инструментов, для которых требуется быстрый и простой способ очистки HTML независимо от того, действителен он или нет. Это медленно и требует слишком много мощности процессора.
-
Ganon (рекомендуется): Универсальный токенизатор и HTML / XML / RSS DOM Parser. У него есть возможность манипулировать элементами и их атрибутами. Он поддерживает недопустимый HTML и UTF8. Он может выполнять расширенные CSS3-подобные запросы к элементам (например, jQuery - поддерживаются пространства имен). Украситель HTML (например, HTML Tidy). Минимизируйте CSS и Javascript. Сортировка атрибутов, изменение регистра символов, правильный отступ и т. Д. Расширяемый. Операции разделены на более мелкие функции для упрощения переопределения и Быстро и легко использовать.
Веб-службы:
- Если вы не хотите программировать PHP, вы также можете использовать веб-службы. Внешний интерфейс ScraperWiki позволяет извлекать данные в желаемой форме для использования в сети или в собственных приложениях. Вы также можете извлечь информацию о состоянии любого скребка.
Я поделился всеми ресурсами, вы можете выбрать по своему вкусу, полезности и т. Д.
Дополнительная литература: newbedev.com/how-do-you-parse-and-process-html-xml-in-php
Обратите внимание: в этом ответе рекомендуются библиотеки, которые были заброшены более 10 лет назад.
phpQuery и QueryPath очень похожи в репликации беглого jQuery API. Вот почему это два самых простых подхода к правильному синтаксическому анализу 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 также позволяет вставлять новые теги в поток (->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. (Первоисточник пропал, так что вот ссылка на интернет-архив. Да, вы все еще можете найти пропавшие страницы, люди.)
Преимущества
- Простота и надежность
- Простые в использовании альтернативы
->find("a img, a object, div a")
- Правильное неэкранирование данных (по сравнению с grepping регулярным выражением)
Я создал библиотеку с именем PHPPowertools/DOM-Query, которая позволяет сканировать документы HTML5 и XML так же, как с jQuery1312. <1509222
Под капотом он использует 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>');
[...]
Поддерживаемые методы:
- [x] (1)
- [x] $ .parseHTML
- [x] $ .parseXML
- [x] $ .parseJSON
- [x] $ selection.add
- [x] $ selection.addClass
- [x] $ selection.after
- [x] $ selection.append
- [x] $ selection.attr
- [x] $ selection.before
- [x] $ selection.children
- [x] $ selection.closest
- [x] $ selection.contents
- [x] $ selection.detach
- [x] $ selection.each
- [x] $ selection.eq
- [x] $ selection.empty (2)
- [x] $ selection.find
- [x] $ selection.first
- [x] $ selection.get
- [x] $ selection.insertAfter
- [x] $ selection.insertBefore
- [x] $ selection.last
- [x] $ selection.parent
- [x] $ selection.parents
- [x] $ selection.remove
- [x] $ selection.removeAttr
- [x] $ selection.removeClass
- [x] $ selection.text
- [x] $ selection.wrap
- Переименовано в select по очевидным причинам
- Переименовано в 'void', поскольку 'empty' является зарезервированным словом в PHP
ПРИМЕЧАНИЕ:
Библиотека также включает собственный автозагрузчик с нулевой конфигурацией для библиотек, совместимых с PSR-0. Приведенный пример должен работать из коробки без какой-либо дополнительной настройки. Кроме того, вы можете использовать его с композитором.
Похоже, что это подходящий инструмент для работы, но он не загружается для меня в PHP 5.6.23 в Worpress. Есть какие-нибудь дополнительные указания о том, как правильно его включить ?. Включил его с: define ("BASE_PATH", dirname ( FILE )); определить ("LIBRARY_PATH", BASE_PATH. DIRECTORY_SEPARATOR. 'lib / vendor'); требуется LIBRARY_PATH. DIRECTORY_SEPARATOR. 'Loader.php'; Loader :: init (массив (LIBRARY_PATH, USER_PATH)); в functions.php
Лучший метод синтаксического анализа 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;
}
Если вы знакомы с селектором 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);
Эта библиотека обычно обрабатывает HTML в автономном режиме менее 1 секунды.
Он также принимает недопустимый HTML или отсутствующие кавычки в атрибутах тегов.
Я создал библиотеку под названием 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;
Почему вам не следует и когда вы должны использовать регулярные выражения?
Во-первых, распространенное неправильное название: регулярные выражения не предназначены для " синтаксического анализа " 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 часто требуют ручной обработки.
- И, наконец, для e чрезвычайно простых задач вроде извлечения <img src = urls, они на самом деле являются вероятным инструментом. Преимущество в скорости по сравнению с синтаксическими анализаторами SGML / XML в основном проявляется только в этих самых простых процедурах извлечения.
Иногда даже рекомендуется предварительно извлечь фрагмент HTML с помощью регулярных выражений /<!--CONTENT-->(.+?)<!--END-->/
и обработать остаток с помощью более простых интерфейсов синтаксического анализатора HTML.
Примечание: На самом деле у меня есть это приложение, в котором я использую синтаксический анализ XML и регулярные выражения в качестве альтернативы. Буквально на прошлой неделе парсинг PyQuery сломался, а регулярное выражение все еще работало. Да, странно, и я сам не могу это объяснить. Но так случилось.
Поэтому, пожалуйста, не отвергайте соображения реального мира только потому, что они не соответствуют мему regex = evil. Но давайте не будем слишком за это голосовать. Это просто отступление от темы.
DOMComment
может читать комментарии, поэтому нет причин использовать для этого Regex.
Ни наборы инструментов SGML, ни анализаторы XML не подходят для синтаксического анализа реального HTML. Для этого подходит только специальный анализатор HTML.
@Alohci DOM
использует libxml и libxml имеет отдельный HTML-синтаксический анализатор модуль HTML, который будет использоваться при загрузке <4768580> HTML-модуля так что он может очень сильно загружать "реальный" (читай сломанный) HTML.
@ Гордон - спасибо. Тем не менее, парсеры HTML и парсеры XML - это разные вещи, даже если они упакованы в одну и ту же библиотеку. И оба они отличаются от реализаций DOM.
Ну, просто комментарий к вашей точке зрения "реального мира". Конечно, для Regex есть полезные ситуации при разборе HTML. А еще есть полезные ситуации для использования GOTO. И есть полезные ситуации для переменных-переменных. Таким образом, никакая конкретная реализация не является окончательной проверкой кода для ее использования. Но это ОЧЕНЬ сильный предупреждающий знак. И средний разработчик вряд ли будет достаточно разбираться в нюансах, чтобы заметить разницу. Итак, как правило, Regex GOTO и переменные-переменные - все зло. Есть и незлое использование, но это исключения (и притом редкие) ... (ИМХО)
@mario: На самом деле HTML можно «правильно» проанализировать с помощью регулярных выражений, хотя обычно требуется несколько из них, чтобы выполнить честно. В общем случае это просто королевская боль. В конкретных случаях с четко определенным вводом это почти тривиально. Это те случаи, когда люди должны использовать регулярные выражения. Большие старые голодные и тяжелые парсеры - это действительно то, что вам нужно в общих случаях, хотя обычному пользователю не всегда ясно, где провести эту черту. Выигрывает тот код, который проще и легче.
Most XML parsers cannot see HTML document comments
Я не уверен, какой парсер вы используете, но мой парсер может "читать" комментарии. -1
С помощью FluidXML вы можете запрашивать и выполнять итерацию XML, используя XPath и CSS-селекторы .
$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');
});
Есть много способов обработки HTML / XML DOM, большинство из которых уже упоминалось. Следовательно, я не буду пытаться перечислять их сам.
Я просто хочу добавить, что лично я предпочитаю использовать расширение DOM и почему:
- iit оптимально использует преимущество в производительности базового кода C
- это OO PHP (и позволяет мне его подклассифицировать)
- это довольно низкий уровень (что позволяет мне использовать его как не раздутую основу для более продвинутого поведения)
- он обеспечивает доступ ко всем частям DOM (в отличие, например, от SimpleXml, который игнорирует некоторые из менее известных функций XML)
- он имеет синтаксис, используемый для сканирования DOM, который аналогичен синтаксису, используемому в собственном Javascript.
И хотя мне не хватает возможности использовать селекторы CSS для DOMDocument
, есть довольно простой и удобный способ добавить эту функцию: создать подкласс DOMDocument
и добавить JS-подобные методы querySelectorAll
и querySelector
в ваш подкласс.
Для разбора селекторов я рекомендую использовать очень минималистичный компонент CssSelector из фреймворка Symfony. Этот компонент просто переводит селекторы CSS в селекторы XPath, которые затем можно передать в DOMXpath
для получения соответствующего списка узлов.
Затем вы можете использовать этот (все еще очень низкий уровень) подкласс в качестве основы для более высокоуровневых классов, предназначенных, например, для. анализировать очень конкретные типы 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 Фабиеном Потенсье о его решении создать компонент CssSelector для Symfony и о том, как его использовать.
Advanced Html Dom представляет собой простую замену HTML DOM, предлагающую тот же интерфейс, но основанный на DOM, что означает отсутствие связанных проблем с памятью.
Он также имеет полную поддержку CSS, включая jQuery расширения.
У меня хорошие результаты от Advanced Html Dom, и я думаю, что он должен быть в списке в принятом ответе. Тем не менее, это важная вещь, которую нужно знать всем, кто полагается на его «Цель этого проекта - стать заменой на основе DOM простой библиотеки HTML dom PHP ... Если вы используете file / str_get_html, вам не нужно изменить что-нибудь ". archive.is/QtSuj#selection-933.34-933.100 заключается в том, что вам может потребоваться внести изменения в свой код, чтобы учесть некоторые несовместимости. Я отметил четыре известных мне проблемы в github проекта. github.com/monkeysuffrage/advanced_html_dom/issues
Есть несколько причин не анализировать 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/")));
JSON и массив из XML в три строки:
$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
Да да!
Для HTML5 библиотека html5 уже много лет заброшена. Единственная библиотека HTML5, которую я могу найти с недавними записями об обновлении и обслуживании, - это html5-php, которая была переведена на бета-версию 1.0 чуть больше недели назад.
Сторонние альтернативы SimpleHtmlDom, которые используют DOM вместо синтаксического анализа строк: phpQuery, Zend_Dom, , QueryPath <>. >
Если вы уже скопировали мои комментарии, по крайней мере, свяжите их должным образом;) Это должно быть: Предлагаемые сторонние альтернативы SimpleHtmlDom, которые фактически используют DOM вместо String Parsing: phpQuery>, Zend_Dom, QueryPath и FluentDom.
Хорошие ответы - отличный источник. coderhelper.com/questions/3606792/…
Для 1a и 2: я бы проголосовал за новый класс Symfony Componet DOMCrawler (DomCrawler). Этот класс позволяет выполнять запросы, аналогичные селекторам CSS. Взгляните на эту презентацию, чтобы увидеть примеры из реального мира: news-of-the-symfony2-world.
Компонент разработан для автономной работы и может использоваться без Symfony.
Единственный недостаток в том, что он будет работать только с PHP 5.3 или новее.
Запросы css, подобные jquery, - это хорошо сказано, потому что есть некоторые вещи, которые отсутствуют в документации w3c, но присутствуют в качестве дополнительных функций в jquery.
Я написал 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
Я рекомендую PHP Simple HTML DOM Parser.
В нем действительно есть приятные особенности, например:
foreach($html->find('img') as $element)
echo $element->src . '<br>';
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
не будет изменен, и вы можете повторно использовать набор результатов снова и снова, возможно, кто-нибудь с гораздо большими знаниями сможет немного прояснить это, но в основном это похоже на то, что я нашел.
Да, для этой цели вы можете использовать simple_html_dom. Однако я довольно много работал с simple_html_dom, особенно для парсинга веб-страниц, и обнаружил, что он слишком уязвим. Он выполняет основную работу, но я все равно не рекомендую его.
Я никогда не использовал curl для этой цели, но я узнал, что curl может выполнять эту работу намного эффективнее и более надежен.
Пожалуйста, ознакомьтесь с этой ссылкой: scraping-sites-with-curl
curl может получить файл, но не будет анализировать HTML за вас. Это самая сложная часть.
Фреймворк Symfony имеет пакеты, которые могут анализировать HTML, и вы можете использовать стиль CSS, чтобы выбрать DOMs вместо использования <561110640550>.
Раньше мы создали довольно много поисковых роботов для наших нужд. В конце концов, обычно лучше всего работают простые регулярные выражения. Хотя перечисленные выше библиотеки хороши по той причине, по которой они созданы, если вы знаете, что ищете, регулярные выражения - более безопасный способ, поскольку вы можете обрабатывать также недопустимые HTML / Структуры XHTML, которые не работают, если загружены через большинство парсеров.
Другой вариант, который вы можете попробовать, - QueryPath. Он вдохновлен jQuery, но на сервере в PHP и используется в Drupal.
Один общий подход, о котором я здесь не упоминал, - это запуск HTML через Tidy, который может быть настроен на выдачу гарантированно действительного XHTML. Затем вы можете использовать на нем любую старую библиотеку XML.
Но для решения вашей конкретной проблемы вам следует взглянуть на этот проект: http://fivefilters.org/content-only/ - это модифицированная версия Читаемость алгоритм, который предназначен для извлечения только текстового содержимого (не верхних и нижних колонтитулов) со страницы.
Звучит как хорошее описание задачи технологии W3C XPath. Легко выразить такие запросы, как «вернуть все атрибуты href
в тегах img
, вложенных в <foo><bar><baz> elements
». Не будучи поклонником PHP, я не могу сказать вам, в какой форме может быть доступен XPath. Если вы можете вызвать внешнюю программу для обработки HTML-файла, вы сможете использовать версию XPath для командной строки.
Краткое введение см. На http://en.wikipedia.org/wiki/XPath.
Это обычно называется очисткой экрана , кстати. Для этого я использовал библиотеку Simple HTML Dom Parser.
Не совсем верно (en.wikipedia.org/wiki/Screen_scraping#Screen_scraping). Подсказка находится в «экране»; в описанном случае экран не задействован. Хотя, по общему признанию, в последнее время этим термином очень часто злоупотребляли.
Я не занимаюсь парсингом экрана, контент, который будет анализироваться, будет разрешен поставщиком контента в соответствии с моим соглашением.
Попробуйте Простой анализатор HTML DOM .
- Парсер HTML DOM, написанный на PHP 5+, который позволяет очень легко манипулировать HTML!
- Требуется PHP 5+.
- Поддерживает недопустимый HTML.
- Находите теги на HTML-странице с помощью таких же селекторов, как jQuery.
- Извлечь содержимое из HTML в одну строку.
- Загрузить
Примечание: как следует из названия, он может быть полезен для простых задач. Он использует регулярные выражения вместо анализатора HTML, поэтому будет значительно медленнее для более сложных задач. Основная часть его кодовой базы была написана в 2008 году, с тех пор были внесены лишь небольшие улучшения. Он не соответствует современным стандартам кодирования PHP, и его будет сложно включить в современный проект, совместимый с PSR.
Примеры :
Как получить элементы 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);
Ну, во-первых, есть вещи, к которым мне нужно подготовиться, например, плохой DOM, код Invlid, а также анализ js против движка DNSBL, это также будет использоваться для поиска вредоносных сайтов / контента, а также потому, что я построил свой сайт на основе i он должен быть чистым, читаемым и хорошо структурированным. SimpleDim великолепен, но код немного запутан
@Robert, вы также можете посетить htmlpurifier.org, чтобы узнать о вещах, связанных с безопасностью.
У него есть один верный момент: simpleHTMLDOM трудно расширить, если вы не используете шаблон декоратора, который я считаю громоздким. Я обнаружил, что содрогаюсь , просто внося изменения в базовый класс (классы).
Я прогнал свой html через tidy перед отправкой в SimpleDOM.
Я использую это в настоящее время, запускаю его как часть проекта для обработки нескольких сотен URL-адресов. Это становится очень медленным, и регулярные тайм-ауты сохраняются. Это отличный сценарий для начинающих, интуитивно простой в освоении, но слишком простой для более сложных проектов.
Просто используйте DOMDocument-> loadHTML () и покончите с этим. Алгоритм синтаксического анализа HTML в libxml довольно хорош и быстр и, вопреки распространенному мнению, не подавляется искаженным HTML.
Истинный. И он работает со встроенными в PHP классами XPath и XSLTProcessor, которые отлично подходят для извлечения контента.
Для действительно искаженного HTML вы всегда можете запустить его через htmltidy, прежде чем передать его в DOM. Когда мне нужно очистить данные из HTML, я всегда использую DOM или, по крайней мере, simplexml.
Еще одна проблема с загрузкой искаженного HTML i, что было бы разумно вызвать libxml_use_internal_errors (true), чтобы предотвратить предупреждения, которые остановят синтаксический анализ.
Я использовал DOMDocument для анализа около 1000 источников html (на разных языках с разными кодировками) без каких-либо проблем. При этом вы можете столкнуться с проблемами кодирования, но они не являются непреодолимыми. Вам нужно знать 3 вещи: 1) loadHTML использует кодировку метатега для определения кодировки 2) # 2 может привести к некорректному обнаружению кодировки, если содержимое html не включает эту информацию 3) неправильные символы UTF-8 могут отключать анализатор. В таких случаях используйте комбинацию mb_detect_encoding () и Simplepie RSS Parser для кодирования / преобразования / удаления плохого кода символов UTF-8 для обходных путей.
Да, но DOMDocument не поддерживает запросы CSS и XPATH, просто getElementById или getElementsByTagName?
Моя проблема с loadHTML - это добавляемые им дополнительные узлы, которые, предположительно, предназначены для «исправления» HTML, но на самом деле не требуются спецификацией DOM. Таким образом, результат вызова loadHTML плохо определен. Было бы намного лучше, если бы подобное происходило в saveHTML.
DOM действительно поддерживает XPath, взгляните на DOMXPath.
Я предпочитаю использовать DOMDocument-> loadHTML () в сочетании с компонентом Symfony «CSSSelector», который переводит селекторы CSS в селекторы XPath. Он по-прежнему очень низкий уровень и делает DOM намного проще в использовании для тех, у кого большой опыт в программировании внешнего интерфейса (подробнее см. coderhelper.com/questions/3577641/…)
Вы можете попробовать использовать что-то вроде HTML Tidy, чтобы очистить любой "сломанный" HTML и преобразовать HTML в XHTML, который затем можно проанализировать с помощью анализатора XML.
Simple HTML DOM - отличный синтаксический анализатор с открытым исходным кодом:
Он обрабатывает элементы DOM объектно-ориентированным способом, и новая итерация имеет большой охват для несовместимого кода. Есть также несколько замечательных функций, подобных тому, что вы видели в JavaScript, например, функция «find», которая возвращает все экземпляры элементов с этим именем тега.
Я использовал это в ряде инструментов, тестировал его на разных типах веб-страниц, и я считаю, что он отлично работает.
XML_HTMLSax
довольно стабилен - даже если он больше не поддерживается. Другой вариант - передать HTML-код через Html Tidy, а затем проанализировать его с помощью стандартных инструментов XML.
@Naveed, это зависит от ваших потребностей. Мне не нужны запросы CSS Selector, поэтому я использую DOM исключительно с XPath. phpQuery стремится стать портом jQuery. Zend_Dom легкий. Вы действительно должны проверить их, чтобы увидеть, какой из них вам больше нравится.
s / HTML5 / HTML / g. Синтаксические конструкции, допускаемые HTML5, в основном уже разрешены в любой предыдущей версии HTML.
@ Ms2ger В основном, но не полностью. Как уже указывалось выше, вы можете использовать парсеры на основе libxml, но есть особые случаи, когда они будут подавляться. Если вам нужна максимальная совместимость, вам лучше использовать специальный парсер. Я предпочитаю сохранять различие.
Ваша точка зрения не использовать PHP Simple HTML DOM Parser кажется спорной.
По состоянию на 29 марта 2012 г. DOM не поддерживает html5, XMLReader не поддерживает HTML, а последняя фиксация html5lib для PHP произошла в сентябре 2009 г. Что использовать для синтаксического анализа HTML5, HTML4 и XHTML?
В ответе @Shiplu выше перечислены все варианты, которые я знаю. DOM может анализировать все, что имеет схему или DTD. HTML5 этого не делает (официально).
Просто чтобы добавить немного опыта: я использовал некоторые из них и теперь всегда рекомендую ganon, так как в большинстве (моих) случаев он на самом деле намного быстрее, чем даже нативные версии из-за того, как он работает, а также очень хорошо работает с недействительные / поврежденные / неполные документы (с которыми никто из других, о которых я знаю, вообще не справляется). Иногда также стоит просто вернуться к написанию собственного или использовать регулярное выражение, но это ТОЛЬКО если у вас есть очень особые и простые требования (например, должны поддерживать только 2 тега в фиксированном формате)
@Jimmy ничего не говорит о cURL, потому что cURL не является инструментом для синтаксического анализа и обработки HTML / XML. cURL - это клиент для различных сетевых протоколов. Например, с его помощью вы можете загружать веб-сайты. В большинстве вышеперечисленных библиотек есть способы загрузки удаленных URL-адресов напрямую, поэтому вам вообще не нужен cURL, например, DOM имеет
loadHTMLFile()
.Что касается сторонних библиотек (на основе libxml), я обнаружил, что: - QueryPath не работает для меня, поскольку он подавился искаженным HTML (даже с использованием htmlqp ()) - к phpQuery немного труднее подойти. Кроме того - html5lib имеет очень активный часть python, но порт php кажется неприхотливым. Если вы ищете быстрое и грязное решение, я могу порекомендовать github.com/hkk12369/php-html-parser
@Gordon Я предлагаю добавить компонент Symfony «CSSSelector» для добавления сканирования DOM на основе «CSS-селектора» в DOMDocument (как описано в coderhelper.com/questions/3577641/…) и компонент Symfony «DOMCrawler», в зависимости от хотите ли вы низкоуровневый доступ к DOM или подход более высокого уровня.
Воспоминание? Вы не можете анализировать (X) HTML с помощью регулярных выражений! (В тот день, когда я его прочитал, меня поразило, что теперь я считаю, что упоминание регулярных выражений рядом с HTML является грехом.)
@Nasha Я намеренно исключил печально известную тираду Zalgo из приведенного выше списка, потому что она сама по себе не слишком полезна и приводит к довольно некоторому культу карго с момента ее написания. Люди получали эту ссылку, независимо от того, насколько подходящим решением было бы регулярное выражение. Чтобы получить более взвешенное мнение, перейдите по ссылке, которую я включил вместо , и просмотрите комментарии на coderhelper.com/questions/4245008/…
Класс TagFilter в Ultimate Web Scraper Toolkit явно отсутствует в этом списке. Я использовал Simple HTML DOM в течение многих лет, потому что это была самая надежно согласованная вещь, которую я мог найти. TagFilter - это то, что я написал изначально, потому что мне нужно было иметь возможность чисто обрабатывать Word HTML, но затем я понял, что могу заменить как Simple HTML DOM, так и HTMLPurifier чем-то гораздо более гибким, масштабируемым (для обработки файлов HTML размером в несколько МБ без памяти утечки), и намного быстрее. В случае библиотеки 1 МБ + HTMLPurifier она намного меньше и автономна. Это тоже поддерживается.
@ Гордон, спасибо за фантастически отличный ответ. Сейчас ему 10 лет, я бы не подумал, что вы сможете сделать обновление к 2021 году?
@ scott8035 Спасибо. Я понятия не имею о текущих библиотеках XML. Я бы, наверное, по-прежнему использовал собственное расширение DOM