Avatar ·

Как правильно парсить HTML и XML в PHP: разбор популярных методов и библиотек

Всем привет! Я начинающий PHP-разработчик и столкнулся с проблемой парсинга HTML и XML. Мне нужно извлечь данные с внешнего сайта (например, заголовки новостей и ссылки), а также обработать XML-фиды от партнёров. Проблема в том, что я пробовал использовать регулярные выражения, но код получается ужасным и ломается при малейшем изменении HTML. Например, я написал такой код: ```php $html = file_get_contents('https://example.com'); preg_match('/

(.*?)<\/h2>/', $html, $matches); echo $matches[1]; ``` Но если на сайте меняется структура или появляются переносы строк, всё перестаёт работать. Кроме того, я читал, что для XML есть SimpleXML, но он не работает с HTML, а DOMDocument вроде бы умеет и то, и другое. Но я запутался: какой инструмент выбрать для каждой задачи? Подскажите, пожалуйста: 1. Как правильно парсить HTML с учётом возможных ошибок в разметке? 2. Как работать с XML (например, RSS-ленты)? 3. Какие библиотеки лучше использовать для сложных случаев (например, когда HTML сломан)? Буду благодарен за примеры кода и объяснение плюсов/минусов каждого подхода. <<>> ### Используйте DOMDocument и DOMXPath для HTML, SimpleXML для XML Вы на верном пути: регулярные выражения **не подходят** для парсинга HTML/XML, так как эти форматы не являются регулярными языками. Вот правильные инструменты для каждой задачи. #### 1. Парсинг HTML с DOMDocument + DOMXPath Это стандартный способ для работы с (X)HTML. DOMDocument может загружать HTML, исправляя мелкие ошибки, а DOMXPath позволяет гибко выбирать элементы. ```php loadHTML($html); libxml_clear_errors(); // Создаём XPath для выборки $xpath = new DOMXPath($dom); // Пример 1: Выбрать все h2 с классом "title" $titles = $xpath->query('//h2[@class="title"]'); foreach ($titles as $title) { echo $title->textContent . "\n"; } // Пример 2: Выбрать ссылки внутри div с id="content" $links = $xpath->query('//div[@id="content"]//a/@href'); foreach ($links as $link) { echo $link->nodeValue . "\n"; } ?> ``` **Ключевые моменты:** - `libxml_use_internal_errors(true)` — отключает вывод ошибок о некорректном HTML. - `DOMXPath::query()` принимает XPath-выражения — это мощнее и стабильнее, чем регулярки. - Для получения текста используйте `->textContent`, для атрибутов — `->getAttribute('href')` или `->nodeValue`. #### 2. Парсинг XML с SimpleXML Для XML (RSS, API-ответы) используйте SimpleXML — он проще и быстрее. ```php channel->item as $item) { echo "Заголовок: " . $item->title . "\n"; echo "Ссылка: " . $item->link . "\n"; echo "Дата: " . $item->pubDate . "\n"; } // Доступ к атрибутам $xml = simplexml_load_string('PHP Guide'); echo $xml['id']; // 123 echo $xml->title; // PHP Guide ?> ``` **Важно:** SimpleXML **не умеет** парсить HTML — только строгий XML. Для HTML используйте DOMDocument. #### 3. Для сложного/сломанного HTML — DOMDocument + LIBXML_HTML_NOIMPLIED Иногда HTML настолько кривой, что DOMDocument создаёт лишние обёртки (DOCTYPE, html, body). Используйте флаг: ```php $dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); ``` Это уберёт автоматическое добавление ``. #### 4. Альтернативы для продвинутых случаев - **PHP Simple HTML DOM Parser** (сторонняя библиотека) — работает как jQuery, но медленнее и не обновлялась давно. Подходит для простых задач. - **DiDOM** (современная библиотека) — быстрее, поддерживает CSS-селекторы. Установка: `composer require imangazaliev/didom`. - **Symfony DomCrawler** — часть Symfony, мощный инструмент для сложного парсинга. #### Сводная таблица | Инструмент | Для чего | Плюсы | Минусы | |------------|----------|-------|--------| | DOMDocument + XPath | HTML/XML | Встроенный, мощный XPath | Много кода для простых задач | | SimpleXML | XML | Очень простой, быстрый | Не работает с HTML | | DiDOM | HTML | CSS-селекторы, современный | Требует Composer | | Регулярки | Никогда | Быстро для простых строк | Ломается при изменениях HTML | **Главный совет:** забудьте про регулярные выражения для HTML/XML. Используйте DOMDocument для HTML и SimpleXML для XML — это покрывает 90% задач. <<>> ### Альтернативный подход: библиотека DiDOM с CSS-селекторами Если вы привыкли к jQuery-подобному синтаксису и не хотите писать громоздкие XPath-запросы, отличным выбором будет библиотека **DiDOM**. Она проста в установке и использовании. Установка через Composer: ```bash composer require imangazaliev/didom ``` Пример парсинга HTML: ```php find('h2.title'); // все h2 с классом "title" foreach ($titles as $title) { echo $title->text() . "\n"; } // Поиск по атрибутам $links = $document->find('div#content a[href]'); foreach ($links as $link) { echo $link->attr('href') . "\n"; } // Работа с XML тоже поддерживается $document = new Document(); $document->loadXml('Data'); echo $document->find('item')[0]->text(); // Data ?> ``` **Плюсы DiDOM:** - Интуитивные CSS-селекторы (как в jQuery) - Автоматическая обработка кодировки - Поддержка как HTML, так и XML - Хорошая производительность **Минусы:** - Требуется установка через Composer (не встроенная библиотека) - Немного тяжелее, чем чистый DOMDocument Если вам нужно быстро написать парсер и вы не хотите разбираться с XPath, DiDOM — идеальный выбор. Для production-проектов рекомендую комбинировать: SimpleXML для XML-фидов, DiDOM для сложного HTML, а для максимальной производительности — встроенный DOMDocument + XPath.