К содержимому

Документация

PHP SDK: Обход страниц и категорий

Если каталог содержит 20 страниц, чтение только первой соберёт лишь часть товаров. Сначала определите механизм перехода: ссылка «Следующая», номер страницы, курсор API или кнопка «Показать ещё».

Пример: переход по ссылке «Следующая»

В параметрах запуска задайте catalog_url. Селекторы .product-card и a.next замените своими. В схеме сайта нужны поля sku и name.

<?php
function run(\Sdk\Context $ctx): void
{
    $url = (string) $ctx->param('catalog_url', '');
    if ($url === '') {
        $ctx->abort('Укажите catalog_url');
    }
    $visited = [];
    $maxPages = (int) $ctx->param('max_pages', 100);
    $page = 0;
    while ($url !== '') {
        if ($ctx->cancelled()) {
            $ctx->abort('Сбор отменён');
        }
        if (isset($visited[$url])) {
            $ctx->abort('Пагинация вернула уже обработанную страницу');
        }
        if ($page >= $maxPages) {
            $ctx->abort('Достигнут max_pages. Каталог собран не полностью');
        }
        $visited[$url] = true;
        $response = $ctx->http()->get($url);
        if (!$response->ok()) {
            $ctx->abort('Не удалось прочитать страницу: HTTP ' . $response->status);
        }
        $dom = $response->dom();
        $cards = $dom->qa('.product-card');
        if (count($cards) === 0) {
            $ctx->abort('Пустая страница каталога. Проверьте снимок');
        }
        foreach ($cards as $card) {
            $sku = $card->attr('data-sku');
            if ($sku === null) {
                $ctx->log('Карточка без артикула', ['page' => $page + 1], 'warning');
                continue;
            }
            $ctx->emit(['sku' => $sku, 'name' => $card->q('.product-title')?->text()], $sku);
        }
        $page++;
        $ctx->progress($page, null, 'Обходим страницы каталога');
        $ctx->log('Страница готова', ['page' => $page, 'cards' => count($cards)]);
        $url = $dom->q('a.next')?->abs() ?? '';
    }
    $ctx->progress($page, $page, 'Обход каталога завершён');
}

Защита visited останавливает цикл, если сайт возвращает одну и ту же ссылку. max_pages защищает от бесконечного обхода, но достижение этого предела считается неполным сбором. Не завершайте такой прогон сообщением «всё готово».

Если известен диапазон страниц

SDK поддерживает $ctx->http()->pages($template, $from, $to). Шаблон использует {page}. Например https://shop.example.invalid/catalog?page={page}. Последнюю страницу нужно определить по данным сайта. Не подставляйте постоянное число наугад: ассортимент может вырасти.

Если есть категории, сначала получите все ссылки на категории, удалите повторы, затем обойдите страницы каждой. Один товар может встречаться в нескольких категориях. Используйте общий стабильный ключ товара и отдельно решите, как хранить список категорий.

Частые ошибки

  • Кнопка «Далее» существует, но отключена. Уточните селектор или проверяйте её состояние.
  • На каждой странице меняются служебные query-параметры. Нормализуйте ссылки, иначе visited не распознает повтор.
  • Сервер возвращает 200 со страницей проверки доступа. Проверяйте наличие карточек, а не только статус HTTP.
  • Цена и остатки есть только в карточке товара. После списка добавьте отдельный этап чтения карточек.

До публикации сравните число страниц и несколько товаров из начала, середины и конца каталога.