Перейти к основному содержимому

Обход магазина

Чтобы собрать все данные с демонстрационного магазина Warehouse, сначала нужно посетить все страницы с товарами - просмотреть все доступные категории и страницы с подробным описанием товаров.

Обход страниц списка товаров

В предыдущих уроках вы использовали функцию enqueueLinks() таким образом:

await enqueueLinks();

Хотя это было полезно в том сценарии, сейчас нам нужно что-то другое. Вместо поиска всех элементов <a href=".."> со ссылками на тот же домен, нам нужно найти только те конкретные ссылки, которые приведут наш краулер к следующей странице результатов. В противном случае краулер посетит множество других страниц, которые нам не интересны. Используя возможности DevTools и еще один параметр enqueueLinks(), это становится довольно простым.

import { PlaywrightCrawler } from 'crawlee';

const crawler = new PlaywrightCrawler({
requestHandler: async ({ page, request, enqueueLinks }) => {
console.log(`Обработка: ${request.url}`);

// Выполняем эту логику только на главной странице категорий, не на подстраницах
if (request.label !== 'CATEGORY') {

// Ждем, пока карточки категорий загрузятся,
// иначе enqueueLinks ничего не добавит в очередь
await page.waitForSelector('.collection-block-item');

// Добавляем ссылки в очередь, но только из
// элементов, соответствующих указанному селектору
await enqueueLinks({
selector: '.collection-block-item',
label: 'CATEGORY',
});
}
},
});

await crawler.run(['https://warehouse-theme-metal.myshopify.com/collections']);

Код должен выглядеть довольно знакомым. Это простой requestHandler, который выводит в консоль URL текущей обрабатываемой страницы и добавляет в очередь новые ссылки. Но есть также несколько новых интересных дополнений. Давайте разберем их.

Когда вы ранее использовали enqueueLinks(), вы не указывали параметр selector, и это было нормально, потому что использовалось значение по умолчанию - a, которое находит все элементы <a>. Но теперь нужно быть более конкретными. На странице категорий есть множество ссылок <a>, а нам нужны только те, которые ведут к списку результатов. Используя DevTools, вы обнаружите, что нужные ссылки можно выбрать с помощью селектора .collection-block-item, который выбирает все элементы с атрибутом class=collection-block-item.

Вы часто будете встречать использование label в Crawlee, так как это удобный способ пометить экземпляр Request для быстрой идентификации позже. Вы можете получить к нему доступ через request.label, это строковое значение. Вы можете называть свои запросы как угодно. Здесь мы использовали метку CATEGORY, чтобы отметить, что мы добавляем в очередь страницы, представляющие категорию товаров. Функция enqueueLinks() добавит эту метку ко всем запросам перед их добавлением в RequestQueue. Почему это полезно, станет очевидно через минуту.

Обход страниц с подробным описанием

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

import { PlaywrightCrawler } from 'crawlee';

const crawler = new PlaywrightCrawler({
requestHandler: async ({ page, request, enqueueLinks }) => {
console.log(`Обработка: ${request.url}`);
if (request.label === 'DETAIL') {
// Пока мы ничего не делаем с деталями
} else if (request.label === 'CATEGORY') {
// Мы находимся на странице категории. Мы можем использовать это для
// перехода по страницам и добавления в очередь всех товаров,
// а также всех последующих страниц, которые найдем

await page.waitForSelector('.product-item > a');
await enqueueLinks({
selector: '.product-item > a',
label: 'DETAIL', // <= обратите внимание на другую метку
});

// Теперь нужно найти кнопку "Следующая" и добавить следующую страницу
// результатов в очередь (если она существует)
const nextButton = await page.$('a.pagination__next');
if (nextButton) {
await enqueueLinks({
selector: 'a.pagination__next',
label: 'CATEGORY', // <= обратите внимание на ту же метку
});
}
} else {
// Это значит, что мы на начальной странице, без метки.
// На этой странице мы просто хотим добавить в очередь все страницы категорий

await page.waitForSelector('.collection-block-item');
await enqueueLinks({
selector: '.collection-block-item',
label: 'CATEGORY',
});
}
},
});

await crawler.run(['https://warehouse-theme-metal.myshopify.com/collections']);

Код обхода теперь завершен. Когда вы запустите код, вы увидите, как краулер посещает все URL списков и все URL с подробным описанием.

Следующие шаги

На этом урок по обходу завершается, поскольку вы научили краулер посещать все необходимые страницы. Давайте продолжим со сбором данных.