Как получить дерево категорий из HTML кода

    Извлечение иерархической структуры категорий из HTML-разметки - частая задача при парсинге интернет-магазинов. В исходном коде категории часто представлены вложенными списками ul и li с классами nested и allow-dropdown. Разберём, как правильно собрать такое дерево с помощью PHP и JavaScript.

    Структура HTML для парсинга категорий

    Типичная разметка содержит контейнер div.drop, внутри которого находятся несколько блоков ul.menuItems. Каждый элемент верхнего уровня может быть:

    • Обычной ссылкой (без вложенности) - <li><a>...</a></li>;
    • Категорией с подкатегориями - <li class="nested"> + <li class="allow-dropdown"> с ul.menuDropItems.

    Важно учитывать, что подкатегории могут быть только у элементов с классом nested, а список подкатегорий находится в соседнем li.allow-dropdown.

    Метод 1: Парсинг на PHP с DOMDocument

    PHP предоставляет встроенные классы DOMDocument и DOMXPath для работы с HTML. Пример алгоритма:

    1. Загрузите HTML-код в DOMDocument;
    2. Найдите все ul.menuItems;
    3. Для каждого li внутри проверьте наличие класса nested;
    4. Если класс есть, извлеките название из span.link-title, а подкатегории - из следующего li.allow-dropdown > ul.menuDropItems > li > a.
    $html = '...'; // ваш HTML
    $dom = new DOMDocument();
    @$dom->loadHTML($html);
    $xpath = new DOMXPath($dom);
    $items = $xpath->query("//ul[contains(@class, 'menuItems')]/li[contains(@class, 'nested')]");
    foreach ($items as $item) {
        $title = $xpath->query(".//span[@class='link-title']", $item)->item(0)->nodeValue;
        $subs = $xpath->query("following-sibling::li[contains(@class, 'allow-dropdown')]//ul[contains(@class, 'menuDropItems')]/li/a", $item);
        // собираем подкатегории
    }
    

    Метод 2: Извлечение с помощью JavaScript в браузере

    Если нужно получить дерево на стороне клиента, используйте querySelectorAll и обход DOM. Скрипт собирает объект, где ключи - названия родительских категорий, а значения - массивы подкатегорий.

    const categories = {};
    document.querySelectorAll('ul.menuItems').forEach(ul => {
        const nested = ul.querySelector('li.nested');
        if (!nested) return;
        const parentName = nested.querySelector('.link-title').textContent.trim();
        const subItems = ul.querySelector('li.allow-dropdown ul.menuDropItems');
        if (subItems) {
            categories[parentName] = Array.from(subItems.querySelectorAll('a')).map(a => a.textContent.trim());
        }
    });
    console.log(categories);
    

    Обработка категорий без подкатегорий

    Некоторые элементы не имеют вложенности - это простые ссылки (<li><a>...</a></li>). Их можно добавить в отдельный массив или в дерево с пустым списком подкатегорий. В примере выше такие узлы игнорируются, но при необходимости их легко учесть, проверив отсутствие класса nested.

    Типичные ошибки при парсинге

    • Игнорирование пробелов и переносов строк - всегда используйте trim() для текста.
    • Неправильные XPath-запросы - проверяйте селекторы в консоли браузера.
    • Динамическая подгрузка - если дерево формируется через JavaScript, дождитесь загрузки страницы.

    Теперь вы знаете, как спарсить иерархию категорий из вложенных списков. Выбирайте подход в зависимости от задачи: PHP для серверной обработки, JavaScript - для клиентской.

    Часто задаваемые вопросы