Как можно разобрать HTML / XML и извлечь из него информацию?
Как вы разбираете и обрабатываете HTML / XML в PHP?
Ответы (30)
Собственные расширения 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 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 предоставляет гибкий XML-интерфейс, похожий на jQuery, для DOMDocument в PHP. Селекторы написаны на XPath или CSS (с использованием конвертера CSS в XPath). Текущие версии расширяют DOM, реализуя стандартные интерфейсы, и добавляют функции из DOM Living Standard. FluentDOM может загружать такие форматы, как JSON, CSV, JsonML, RabbitFish и другие. Может быть установлен через Composer.
HtmlPageDom
Wa72 \ HtmlPageDom` - это библиотека PHP для простого управления документами HTML с помощью. Для перехода требуется DomCrawler из компонентов Symfony2 дерево DOM и расширяет его, добавляя методы для управления деревом DOM документов HTML.
phpQuery (не обновлялся годами)
phpQuery - это серверный API-интерфейс объектной модели документа (DOM), управляемый селектором CSS3, на стороне сервера, написанный на 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.
saber / 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 апреля не было никаких ответов на исправления.
Ganon
- Универсальный токенизатор и парсер 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 парсинг, который стоит проверить.
Веб-сервисы
Если вам не нравится программировать PHP, вы также можете использовать веб-службы. В общем, я нашел для них очень мало полезности, но это только я и мои варианты использования.
ScraperWiki.
Внешний интерфейс ScraperWiki позволяет извлекать данные в желаемой форме для использования в сети или в собственных приложениях. Также вы можете извлечь информацию о состоянии любого скребка.
Регулярные выражения
И последнее и наименее рекомендованное: вы можете извлекать данные из HTML с помощью регулярных выражений. В целом использование регулярных выражений в HTML не рекомендуется.
Большинство фрагментов, которые вы найдете в Интернете для соответствия разметке, являются хрупкими. В большинстве случаев они работают только с определенным фрагментом HTML. Небольшие изменения разметки, такие как добавление пробелов, добавление или изменение атрибутов в теге, могут привести к сбою RegEx, если он неправильно написан. Вы должны знать, что делаете, прежде чем использовать RegEx в HTML.
Парсеры HTML уже знают синтаксические правила HTML. Регулярные выражения необходимо учить для каждого нового написанного вами регулярного выражения. В некоторых случаях RegEx подходят, но это действительно зависит от вашего варианта использования.
Вы можете писать более надежные парсеры, но написание полного и надежного настраиваемого парсера с регулярными выражениями - пустая трата времени, когда вышеупомянутые библиотеки уже существуют и справляются с этим гораздо лучше.
См. Также Разбор Html Путь Ктулху
Книги
Если вы хотите потратить немного денег, взгляните на
Я не связан с PHP Architect или авторами.
loadHTMLFile()
.
- person Gordon; 01.09.2013
Попробуйте Simple 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);
Просто используйте DOMDocument-> loadHTML () и покончите с этим. Алгоритм синтаксического анализа HTML в libxml довольно хорош и быстр и, вопреки распространенному мнению, не подавляется искаженным HTML.
Почему не следует и когда следует использовать регулярные выражения?
Во-первых, распространенное заблуждение: регулярные выражения не предназначены для "синтаксического анализа" 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 сломался, а регулярное выражение все еще работало. Да, странно, и я сам не могу это объяснить. Но так оно и случилось.
Поэтому, пожалуйста, не отвергайте соображения реального мира только потому, что они не соответствуют мему regex = evil. Но давайте также не будем слишком сильно за это голосовать. Это просто отступление от темы.
DOMComment
может читать комментарии, поэтому нет причин использовать для этого Regex.
- person Gordon; 06.09.2010
DOM
использует libxml и libxml имеет отдельный HTML-код. модуль парсера, который будет использоваться при загрузке HTML с помощью _2 _ так что он может очень сильно загружать реальный (читай сломанный) HTML.
- person Gordon; 06.09.2010
Most XML parsers cannot see HTML document comments
Я не уверен, какой парсер вы используете, но мой парсер может читать комментарии. -1
- person hek2mgl; 03.07.2014
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. (Первоисточник пропал, так что вот ссылка на интернет-архив. Да, вы все еще можете найти отсутствующие страницы, люди.)
А вот подробное введение в QueryPath < / а>.
Преимущества
- Простота и надежность
- Простые в использовании альтернативы
->find("a img, a object, div a")
- Правильное неэкранирование данных (по сравнению с grepping регулярным выражением)
Simple HTML DOM - отличный парсер с открытым исходным кодом:
Он обрабатывает элементы DOM объектно-ориентированным способом, и новая итерация имеет большой охват для несовместимого кода. Есть также несколько замечательных функций, подобных тому, что вы видели в JavaScript, например, функция «find», которая возвращает все экземпляры элементов с этим именем тега.
Я использовал это в ряде инструментов, тестировал его на разных типах веб-страниц, и я считаю, что он отлично работает.
Один общий подход, о котором я здесь не упоминал, - это запуск HTML через Tidy, который может быть настроен на выдачу гарантированно действительного XHTML. Затем вы можете использовать на нем любую старую библиотеку XML.
Но что касается вашей конкретной проблемы, вам следует взглянуть на этот проект: http://fivefilters.org/content-only/ - это модифицированная версия алгоритма читабельности, который предназначен для извлечения только текстового содержимого (не верхних и нижних колонтитулов) со страницы.
За 1a и 2: я бы проголосовал за новый класс Symfony Componet DOMCrawler (DomCrawler). Этот класс позволяет выполнять запросы, аналогичные селекторам CSS. Взгляните на эту презентацию, чтобы увидеть реальные примеры: news-of-the -symfony2-world.
Компонент предназначен для автономной работы и может использоваться без Symfony.
Единственный недостаток в том, что он будет работать только с PHP 5.3 или новее.
Кстати, это обычно называется очисткой экрана. Для этого я использовал библиотеку Simple HTML Dom Parser.
Раньше мы создали немало краулеров для наших нужд. В конце концов, обычно лучше всего работают простые регулярные выражения. Хотя перечисленные выше библиотеки хороши по той причине, что они созданы, если вы знаете, что ищете, регулярные выражения - более безопасный способ, поскольку вы можете обрабатывать также недопустимые HTML / XHTML структуры, которые не работают, если загружаются через большинство парсеров.
Я рекомендую PHP Simple HTML DOM Parser.
У него действительно есть приятные особенности, такие как:
foreach($html->find('img') as $element)
echo $element->src . '<br>';
Похоже, это хорошее описание задачи технологии XPath W3C. Легко выразить такие запросы, как «вернуть все href
атрибуты в img
тегах, вложенных в <foo><bar><baz> elements
». Не будучи поклонником PHP, я не могу сказать вам, в какой форме может быть доступен XPath. Если вы можете вызвать внешнюю программу для обработки HTML-файла, вы сможете использовать версию XPath для командной строки. Краткое введение см. На странице http://en.wikipedia.org/wiki/XPath.
Сторонние альтернативы SimpleHtmlDom, использующие DOM вместо анализа строк: phpQuery, Zend_Dom, QueryPath и FluentDom.
Да, вы можете использовать simple_html_dom для этой цели. Однако я довольно много работал с simple_html_dom, особенно для парсинга веб-страниц, и обнаружил, что он слишком уязвим. Он выполняет основную работу, но я все равно не рекомендую его.
Я никогда не использовал curl для этой цели, но я узнал, что curl может выполнять эту работу намного эффективнее и более надежен.
Пожалуйста, ознакомьтесь с этой ссылкой: scraping-sites-with-curl
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
не будет изменен, и вы можете повторно использовать набор результатов снова и снова, возможно, кто-нибудь с гораздо большими знаниями сможет немного прояснить это, но в основном это похоже на то, что я нашел.
Advanced Html Dom - это простой HTML Замена DOM, предлагающая тот же интерфейс, но на основе DOM, что означает, что не возникает никаких связанных проблем с памятью.
Он также имеет полную поддержку CSS, включая расширения jQuery.
Для HTML5 библиотека html5 уже много лет заброшена. Единственная библиотека HTML5, которую я могу найти с недавними записями об обновлении и обслуживании, - это html5- php, который был переведен на бета-версию 1.0 чуть больше недели назад.
Я создал библиотеку с именем PHPPowertools / DOM-Query, которая позволяет вам сканировать документы HTML5 и XML так же, как вы это делаете с jQuery.
Под капотом он использует symfony / DomCrawler для преобразования селекторов CSS в < селекторы href = "http://en.wikipedia.org/wiki/XPath" rel = "noreferrer"> 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", поскольку "пустой" - зарезервированное слово в PHP
ЗАМЕТКА :
Библиотека также включает собственный автозагрузчик с нулевой конфигурацией для библиотек, совместимых с PSR-0. Приведенный пример должен работать из коробки без какой-либо дополнительной настройки. Кроме того, вы можете использовать его с композитором.
Я написал 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
Вы можете попробовать использовать что-то вроде HTML Tidy, чтобы очистить любой "битый" HTML и преобразовать HTML в XHTML. , который затем можно проанализировать с помощью анализатора XML.
XML_HTMLSax
довольно стабилен, даже если он больше не поддерживается. Другой вариант - направить HTML-код через Html Tidy, а затем проанализировать его. с помощью стандартных инструментов XML.
Есть много способов обработки 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 и о том, как его использовать.
С помощью FluidXML вы можете запрашивать и выполнять итерацию XML с помощью XPath < / strong> и Селекторы 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');
});
https://github.com/servo-php/fluidxml
JSON и массив из XML в три строки:
$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
Ta da!
Есть несколько причин не анализировать 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/")));
Я создал библиотеку под названием 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;
Если вы знакомы с селектором 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 или отсутствующие кавычки в атрибутах тегов.
Лучший способ синтаксического анализа 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;
}