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

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


person Community    schedule 26.08.2010    source источник


Ответы (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 вы хотите использовать специальный парсер, например

html5lib

Реализации синтаксического анализатора 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 или авторами.

person Gordon    schedule 26.08.2010
comment
@Naveed, это зависит от ваших потребностей. Мне не нужны запросы CSS Selector, поэтому я использую DOM исключительно с XPath. phpQuery стремится стать портом jQuery. Zend_Dom легкий. Вы действительно должны проверить их, чтобы увидеть, какой из них вам больше нравится. - person Gordon; 26.08.2010
comment
s / HTML5 / HTML / g. Синтаксические конструкции, допускаемые HTML5, в основном уже разрешены в любой предыдущей версии HTML. - person Ms2ger; 19.01.2011
comment
@ Ms2ger В основном, но не полностью. Как уже указывалось выше, вы можете использовать парсеры на основе libxml, но есть особые случаи, когда они будут подавляться. Если вам нужна максимальная совместимость, вам лучше использовать специальный парсер. Я предпочитаю сохранять различие. - person Gordon; 19.01.2011
comment
Ваша точка зрения не использовать PHP Simple HTML DOM Parser кажется спорной. - person Petah; 27.02.2012
comment
По состоянию на 29 марта 2012 г. DOM не поддерживает html5, XMLReader не поддерживает HTML, а последняя фиксация html5lib для PHP произошла в сентябре 2009 г. Что использовать для синтаксического анализа HTML5, HTML4 и XHTML? - person Shiplu Mokaddim; 29.03.2012
comment
В ответе @Shiplu выше перечислены все варианты, которые я знаю. DOM может анализировать все, что имеет схему или DTD. HTML5 этого не делает (официально). - person Gordon; 29.03.2012
comment
Просто чтобы добавить немного опыта: я использовал некоторые из них и теперь всегда рекомендую ganon, поскольку в большинстве (моих) случаев он на самом деле намного быстрее, чем даже нативные версии, из-за того, как он работает, а также очень хорошо работает с недействительные / поврежденные / неполные документы (с которыми никто из других, о которых я знаю, вообще не справляется). Иногда также стоит просто вернуться к написанию собственного или использовать регулярное выражение, но это ТОЛЬКО если у вас есть очень особые и простые требования (например, должны поддерживать только 2 тега в фиксированном формате) - person griffin; 27.08.2013
comment
@Jimmy он ничего не говорит о cURL, потому что cURL не является инструментом для синтаксического анализа и обработки HTML / XML. cURL - это клиент для различных сетевых протоколов. Например, с его помощью вы можете загружать веб-сайты. В большинстве вышеперечисленных библиотек есть способы загрузки удаленных URL-адресов напрямую, поэтому вам вообще не нужен cURL, например, в DOM есть loadHTMLFile(). - person Gordon; 01.09.2013
comment
Что касается сторонних библиотек (на основе libxml), я обнаружил, что: - QueryPath не работает для меня, поскольку он подавился искаженным HTML (даже с использованием htmlqp ()) - к phpQuery немного труднее подойти. Кроме того - html5lib имеет очень активный часть python, но порт php кажется неприхотливым. Если вы ищете быстрое и грязное решение, я могу порекомендовать github.com/hkk12369/php-html-parser - person andig; 15.11.2013
comment
@Gordon Я предлагаю добавить компонент Symfony CSSSelector для добавления сканирования DOM на основе CSS-селектора в DOMDocument (как описано в stackoverflow.com/questions/3577641/) и компонент Symfony DOMCrawler, в зависимости от того, хотите ли вы низкоуровневый доступ к DOM или подход более высокого уровня. - person John Slegers; 03.07.2014
comment
Помнить? Вы не можете анализировать (X) HTML с помощью регулярных выражений! (В тот день, когда я его прочитал, меня поразило, что теперь я считаю, что упоминание регулярных выражений рядом с HTML является грехом.) - person ; 28.04.2015
comment
@Nasha Я намеренно исключил печально известную тираду Zalgo из приведенного выше списка, потому что она сама по себе не слишком полезна и привела к довольно некоторому культу карго с момента ее написания. Люди получали эту ссылку, независимо от того, насколько подходящим решением было бы регулярное выражение. Чтобы получить более сбалансированное мнение, просмотрите ссылку, которую я сделал вместо нее, и просмотрите комментарии на странице stackoverflow.com/questions/4245008/ - person Gordon; 28.04.2015
comment
Класс TagFilter в Ultimate Web Scraper Toolkit явно отсутствует в этом списке. Я использовал Simple HTML DOM в течение многих лет, потому что это была самая надежно согласованная вещь, которую я мог найти. TagFilter - это то, что я написал изначально, потому что мне нужно было иметь возможность чисто обрабатывать Word HTML, но затем я понял, что могу заменить как Simple HTML DOM, так и HTMLPurifier чем-то гораздо более гибким, масштабируемым (для обработки файлов HTML размером в несколько МБ без памяти утечки), и намного быстрее. В случае библиотеки 1 МБ + HTMLPurifier она намного меньше и автономна. Это тоже поддерживается. - person CubicleSoft; 26.03.2018
comment
@ Гордон, спасибо за фантастически отличный ответ. Сейчас ему 10 лет, я бы не подумал, что вы сможете сделать обновление к 2021 году? - person scott8035; 01.01.2021
comment
@ scott8035 Спасибо. Я понятия не имею о текущих библиотеках XML. Я бы, наверное, по-прежнему использовал собственное расширение DOM - person Gordon; 04.01.2021

Попробуйте 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);
person Naveed    schedule 26.08.2010
comment
Ну, во-первых, есть вещи, к которым мне нужно подготовиться, например, плохой DOM, код Invlid, а также анализ js на DNSBL, это также будет использоваться для поиска вредоносных сайтов / контента, а также потому, что я построил свой сайт на основе i он должен быть чистым, читаемым и хорошо структурированным. SimpleDim великолепен, но код немного запутан - person RobertPitt; 26.08.2010
comment
как я уже сказал, я много раз использовал простой DOM, и он отлично, просто искал систему с более чистым, легко расширяемым кодом, OO (P | D) Wise и т. д. - person RobertPitt; 26.08.2010
comment
@Robert, вы также можете проверить htmlpurifier.org, чтобы узнать о безопасности. - person Gordon; 31.08.2010
comment
У него есть один верный момент: simpleHTMLDOM трудно расширить, если вы не используете шаблон декоратора, который я считаю громоздким. Я обнаружил, что содрогнулся, просто внося изменения в базовый класс (классы). - person Erik; 18.09.2010
comment
Я прогнал свой html через tidy перед отправкой в ​​SimpleDOM. - person MB34; 23.04.2012
comment
Я использую это в настоящее время, запускаю его как часть проекта для обработки нескольких сотен URL-адресов. Это становится очень медленным, и регулярные тайм-ауты сохраняются. Это отличный сценарий для начинающих, интуитивно простой в освоении, но слишком простой для более сложных проектов. - person luke_mclachlan; 07.04.2016

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

person Edward Z. Yang    schedule 26.11.2008
comment
Правда. И он работает со встроенными в PHP классами XPath и XSLTProcessor, которые отлично подходят для извлечения контента. - person Kornel; 27.11.2008
comment
Для действительно искаженного HTML вы всегда можете запустить его через htmltidy, прежде чем передать его в DOM. Когда мне нужно очистить данные из HTML, я всегда использую DOM или, по крайней мере, simplexml. - person Frank Farmer; 13.10.2009
comment
Еще одна проблема с загрузкой искаженного HTML i, что было бы разумно вызвать libxml_use_internal_errors (true), чтобы предотвратить предупреждения, которые остановят синтаксический анализ. - person Husky; 24.05.2010
comment
Я использовал DOMDocument для анализа около 1000 источников html (на разных языках с разными кодировками) без каких-либо проблем. При этом вы можете столкнуться с проблемами кодирования, но они не являются непреодолимыми. Вам нужно знать 3 вещи: 1) loadHTML использует кодировку метатега для определения кодировки 2) # 2 может привести к некорректному обнаружению кодировки, если содержимое html не включает эту информацию 3) неправильные символы UTF-8 могут отключать анализатор. В таких случаях используйте комбинацию mb_detect_encoding () и Simplepie RSS Parser для кодирования / преобразования / удаления плохого кода символов UTF-8 для обходных путей. - person Zero; 19.09.2010
comment
Да, но DOMDocument не поддерживает запросы CSS и XPATH, просто getElementById или getElementsByTagName? - person umpirsky; 16.11.2010
comment
Моя проблема с loadHTML - это дополнительные узлы, которые он вставляет, которые, предположительно, предназначены для исправления HTML, но на самом деле не требуются спецификацией DOM. Таким образом, результат вызова loadHTML плохо определен. Было бы намного лучше, если бы подобное происходило в saveHTML. - person CurtainDog; 03.03.2011
comment
DOM действительно поддерживает XPath, взгляните на DOMXPath. - person Ryan McCue; 30.01.2012
comment
Я предпочитаю использовать DOMDocument- ›loadHTML () в сочетании с компонентом Symfony CSSSelector, который переводит селекторы CSS в селекторы XPath. Он по-прежнему очень низкий уровень и делает DOM намного проще в использовании для тех, у кого большой опыт в программировании внешнего интерфейса (см. stackoverflow.com/questions/3577641/ для получения дополнительной информации) - person John Slegers; 03.07.2014

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

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

person Community    schedule 06.09.2010
comment
DOMComment может читать комментарии, поэтому нет причин использовать для этого Regex. - person Gordon; 06.09.2010
comment
Ни наборы инструментов SGML, ни анализаторы XML не подходят для синтаксического анализа реального HTML. Для этого подходит только специальный анализатор HTML. - person Alohci; 06.09.2010
comment
@Alohci DOM использует libxml и libxml имеет отдельный HTML-код. модуль парсера, который будет использоваться при загрузке HTML с помощью _2 _ так что он может очень сильно загружать реальный (читай сломанный) HTML. - person Gordon; 06.09.2010
comment
@ Гордон - спасибо. Тем не менее, парсеры HTML и парсеры XML - это разные вещи, даже если они упакованы в одну и ту же библиотеку. И оба они отличаются от реализаций DOM. - person Alohci; 06.09.2010
comment
Ну, просто комментарий о вашей реальной точке зрения. Конечно, для Regex есть полезные ситуации при разборе HTML. А еще есть полезные ситуации для использования GOTO. И есть полезные ситуации для переменных-переменных. Таким образом, никакая конкретная реализация не является окончательной проверкой кода для ее использования. Но это ОЧЕНЬ сильный предупреждающий знак. И средний разработчик вряд ли будет достаточно разбираться в нюансах, чтобы заметить разницу. Итак, как правило, Regex GOTO и Variable-Variables - зло. Есть и незлое использование, но это исключения (и притом редкие) ... (ИМХО) - person ircmaxell; 07.09.2010
comment
@mario: На самом деле HTML можно «правильно» проанализировать с помощью регулярных выражений, хотя обычно требуется несколько из них, чтобы справиться с задачей. В общем случае это просто королевская боль. В конкретных случаях с четко определенными входными данными это почти тривиально. Это те случаи, когда люди должны использовать регулярные выражения. Большие старые голодные и тяжелые парсеры - это действительно то, что вам нужно в общих случаях, хотя обычному пользователю не всегда ясно, где провести эту черту. Выигрывает тот код, который проще и легче. - person tchrist; 21.11.2010
comment
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 регулярным выражением)
person Community    schedule 07.09.2010

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

simplehtmldom.sourceforge

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

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

person Robert Elwell    schedule 15.11.2008

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

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

person Eli    schedule 01.05.2011

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

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

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

person Community    schedule 06.09.2010
comment
Запросы css, подобные jquery, - это хорошо сказано, потому что есть некоторые вещи, которые отсутствуют в документации w3c, но присутствуют в качестве дополнительных функций в jquery. - person Nikola Petkanski; 13.05.2013

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

person Joel Verhagen    schedule 26.08.2010
comment
Не совсем верно (en.wikipedia.org/wiki/Screen_scraping#Screen_scraping). Подсказка находится на экране; в описанном случае экран не задействован. Хотя, по общему признанию, в последнее время этим термином очень часто злоупотребляли. - person Bobby Jack; 26.08.2010
comment
Я не занимаюсь парсингом экрана, контент, который будет анализироваться, будет разрешен поставщиком контента в соответствии с моим соглашением. - person RobertPitt; 26.08.2010

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

person jancha    schedule 04.10.2011

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

У него действительно есть приятные особенности, такие как:

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

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

person Jens    schedule 14.04.2011

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

person Community    schedule 07.09.2010
comment
Если вы уже скопировали мои комментарии, по крайней мере, свяжите их должным образом;) Это должно быть: Предлагаемые сторонние альтернативы SimpleHtmlDom, которые фактически используют DOM вместо синтаксического анализа строк: phpQuery, Zend_Dom, QueryPath и FluentDom. - person Gordon; 07.09.2010
comment
Хорошие ответы - отличный источник. stackoverflow .com / questions / 3606792 /. - person johnlemon; 08.09.2010

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

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

Пожалуйста, ознакомьтесь с этой ссылкой: scraping-sites-with-curl

person Rafay    schedule 05.01.2012
comment
curl может получить файл, но не будет анализировать HTML за вас. Это самая сложная часть. - person cHao; 21.11.2012

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

person Christopher Thomas    schedule 15.04.2012

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

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

person Community    schedule 18.12.2014
comment
У меня хорошие результаты от 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 - person ChrisJJ; 16.11.2016

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

person Community    schedule 08.07.2013

Я создал библиотеку с именем 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>');

[...]

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


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

ЗАМЕТКА :

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

person Community    schedule 09.07.2015
comment
Похоже, что это подходящий инструмент для работы, но он не загружается для меня в 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 - person lithiumlab; 17.10.2016

Я написал 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

person Community    schedule 12.05.2013

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

person Ric    schedule 31.05.2011

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

person CesarB    schedule 15.11.2008

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

person troelskn    schedule 15.11.2008

Есть много способов обработки 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 и о том, как его использовать.

person Community    schedule 03.07.2014

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

person Tuong Le    schedule 29.12.2011

С помощью 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

person Community    schedule 11.12.2015

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

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

Ta da!

person Community    schedule 15.10.2013

Есть несколько причин не анализировать 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/")));
person Community    schedule 05.12.2013

Я создал библиотеку под названием 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;
person Community    schedule 21.12.2017

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

person Community    schedule 16.08.2018

Лучший способ синтаксического анализа 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;
}
person Community    schedule 29.03.2019