В php парсерах не стоит полагаться на DOMXPath и сторонние библиотеки

При парсинге на php я использую исключительно методы DOMDocument, либо, если не требуется большого количества данных и какой-то сложной выборки элементов, иногда достаточно обойтись регулярками — они работают быстрее. Недавно отказался от xpath, когда обнаружил интересную особенность — делаю правильный xpath запрос к явно существующему элементу и получаю дулю — возвращался «пустой объект». Вернее, объект DOMNodeList был не пустым, он имел свойство length, но вот при переборе этого объекта его DOMNode не имели свойств nodeValue, textContent и канонизировать его узлы методом DOMNode::C14N тоже не получилось — этого метода у нод не было. Вот такой вот «неполноценный» DOMNodeList возвратил мне xpath. А при использовании метода getElementsByTagName и переборе тех же самых элементов, у нод всё оказалось нормально — все свойства и методы были на месте. Вот такая особенность.

Вот поэтому сторонние библиотеки типа phpQuery и класс DOMXPath лучше не использовать. Да, не так элегантно, как с xpath, код получается несколько длиннее, но надёжнее.

<?php
$doc = new DOMDocument();
$doc->loadHTML('<?xml encoding="UTF-8">'.$page); // подгружаем страницу в объект
$div_nodes = $doc->getElementsByTagName('div'); // получаем div ноды
foreach ($div_nodes as $node) { // обходим ноды
    if (stripos($node->getAttribute('class'), 'alert-success') !== false) { // проверяем содержание нужной подстроки в атрибуте класса
        $strong_nodes = $node->getElementsByTagName('strong'); // получаем дочерние ноды тегов strong
        foreach ($strong_nodes as $strong) { // обходим ноды strong
            echo $strong->textContent; // выводим текстовое содержимое нод
        }
    } 
}

Аналогичный код с использованием xpath запроса гораздо короче:

<?php
$doc = new DOMDocument();
$doc->loadHTML('<?xml encoding="UTF-8">'.$page); // подгружаем страницу в объект
$xpath = new DOMXpath($doc); // создаем xpath объект
$strong_nodes = $xpath->query("//div[contains(@class, 'alert-success')]//strong"); // делаем запрос
foreach ($strong_nodes as $strong) { // обходим ноды strong
    echo $strong->textContent; // выводим текстовое содержимое нод
}

 

Оставить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *