it-roy-ru.com

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

Как можно проанализировать HTML/XML и извлечь из него информацию?

2028
RobertPitt

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

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

DOM

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

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

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

Базовый пример использования можно найти в захват атрибута 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 и реализует синтаксический анализатор XML Push в стиле SAX . Это может быть лучшим выбором для управления памятью, чем DOM или SimpleXML, но с ним будет сложнее работать, чем с парсером, реализованным XMLReader.

SimpleXML

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

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

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


Сторонние библиотеки (на основе 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-документами с использованием метода Требуется DomCrawler из компонентов Symfony2 для обхода дерева DOM и расширяет его, добавляя методы для манипулирования деревом DOM HTML-документов.

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

phpQuery - это цепочечный API-интерфейс на основе объектной модели документов (DOM), управляемый селектором на стороне сервера, основанный на JavaScript-библиотеке jQuery, написанный на 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 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 Parser
    • Способность манипулировать элементами и их атрибутами
    • Поддерживает неверный HTML и UTF8
  • Может выполнять расширенные CSS3-подобные запросы к элементам (например, jQuery - поддерживаются пространства имен)
  • HTML beautifier (например, HTML Tidy)
    • Минимизировать CSS и Javascript
    • Сортировать атрибуты, изменить регистр символов, исправить отступы и т.д.
  • Extensible
    • Разбор документов с использованием обратных вызовов на основе текущего символа/токена
    • Операции разделены на меньшие функции для легкого переопределения
  • Быстро и легко

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


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 Архитектором или авторами.

1831
Gordon

Попробуйте Простой 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);
317
Naveed

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

231
Edward Z. Yang

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

Во-первых, распространенное неправильное выражение: регулярные выражения не для " анализа " 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 прервался, и регулярное выражение все еще работало. Да, странно, и я не могу объяснить это сам. Но так случилось.
Поэтому, пожалуйста, не опровергайте реальные соображения, просто потому, что они не соответствуют регулярному выражению = злой мем. Но давайте также не будем слишком много голосовать за это. Это просто sidenote для этой темы.

143
mario

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 также позволяет вставлять новые теги в поток (->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")
  • Правильное удаление данных (по сравнению с регулярными выражениями)
129
mario

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

simplehtmldom.sourceforge

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

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

88
Robert Elwell

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

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

59
Eli

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

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

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

55
Timo

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

52
Joel Verhagen

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

41
jancha

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

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

foreach($html->find('img') as $element)
       echo $element->src . '<br>';
38
Greg

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

36
Jens

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

29
danidacar

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

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

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

24
Rafay

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 не будет изменен, и вы сможете использовать набор результатов снова и снова, возможно, кто-то с гораздо большими знаниями сможет немного прояснить это, но это в основном так из того, что я нашел.

23
Christopher Thomas

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

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

19
pguardiario

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

18
Reid Johnson

Я написал анализатор 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
Paul Warelis

Я создал библиотеку с именем 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. Переименован в "select" по понятным причинам
  2. Переименован в "void", поскольку "пустой" является зарезервированным словом в PHP

НОТА :

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

17
John Slegers

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

15
CesarB

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

15
Richard Le Poidevin

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

12
troelskn

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

11
Tuong Le

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

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

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

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

Для синтаксического анализа селекторов я рекомендую использовать очень минималистичный компонент CssSelector из платформа Symfony . Этот компонент просто переводит селекторы CSS в селекторы XPath, которые затем могут быть переданы в 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 и о том, как его использовать.

11
John Slegers

С 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');
        });

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

9
Daniele Orlando

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

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

Та да!

7
Antonio Max

Есть несколько причин не разбирать 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/")));
7
Daniel Loureiro

Я создал библиотеку под названием 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;
2
Ivo Petkov

Если вы знакомы с селектором 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 или отсутствующую кавычку в атрибутах тега.

0
StefansArya

Лучший метод для разбора 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;
}
0
user8031209