Обход магазина
Чтобы собрать все данные с демонстрационного магазина 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 текущей обрабатываемой страницы и добавляет в очередь новые ссылки. Но есть также несколько новых интересных дополнений. Давайте разберем их.
Параметр selector
функции enqueueLinks()
Когда вы ранее использовали enqueueLinks()
, вы не указывали параметр selector
, и это было нормально, потому что использовалось значение по умолчанию - a
, которое находит все элементы <a>
. Но теперь нужно быть более конкретными. На странице категорий есть множество ссылок <a>
, а нам нужны только те, которые ведут к списку результатов. Используя DevTools, вы обнаружите, что нужные ссылки можно выбрать с помощью селектора .collection-block-item
, который выбирает все элементы с атрибутом class=collection-block-item
.
Параметр label
функции enqueueLinks()
Вы часто будете встречать использование 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 с подробным описанием.
Следующие шаги
На этом урок по обходу завершается, поскольку вы научили краулер посещать все необходимые страницы. Давайте продолжим со сбором данных.