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.
- Цена и остатки есть только в карточке товара. После списка добавьте отдельный этап чтения карточек.
До публикации сравните число страниц и несколько товаров из начала, середины и конца каталога.