Как получить дерево категорий из 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. Пример алгоритма:
- Загрузите HTML-код в
DOMDocument; - Найдите все
ul.menuItems; - Для каждого
liвнутри проверьте наличие классаnested; - Если класс есть, извлеките название из
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 - для клиентской.