Сохранение данных
Процесс извлечения данных не будет полным без их сохранения для дальнейшего использования и обработки. Вы подошли к финальной и самой важной части этого руководства, поэтому будьте особенно внимательны!
Для начала добавьте новый импорт в начало файла:
import { PlaywrightCrawler, Dataset } from 'crawlee';
Затем замените вызов console.log(results) на:
await Dataset.pushData(results);
и это всё. В этот раз мы не шутим. Действительно, это всё что нужно. Вот как выглядит финальный код:
import { PlaywrightCrawler, Dataset } from 'crawlee';
const crawler = new PlaywrightCrawler({
requestHandler: async ({ page, request, enqueueLinks }) => {
console.log(`Processing: ${request.url}`);
if (request.label === 'DETAIL') {
const urlPart = request.url.split('/').slice(-1); // ['sennheiser-mke-440-professional-stereo-shotgun-microphone-mke-440']
const manufacturer = urlPart[0].split('-')[0]; // 'sennheiser'
const title = await page.locator('.product-meta h1').textContent();
const sku = await page.locator('span.product-meta__sku-number').textContent();
const priceElement = page
.locator('span.price')
.filter({
hasText: '$',
})
.first();
const currentPriceString = await priceElement.textContent();
const rawPrice = currentPriceString.split('$')[1];
const price = Number(rawPrice.replaceAll(',', ''));
const inStockElement = page
.locator('span.product-form__inventory')
.filter({
hasText: 'In stock',
})
.first();
const inStock = (await inStockElement.count()) > 0;
const results = {
url: request.url,
manufacturer,
title,
sku,
currentPrice: price,
availableInStock: inStock,
};
await Dataset.pushData(results);
} 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',
});
}
},
// Давайте ограничим наши краулинг, чтобы наши тесты были короче и безопаснее.
maxRequestsPerCrawl: 50,
});
await crawler.run(['https://warehouse-theme-metal.myshopify.com/collections']);
Что такое Dataset.pushData()
Dataset.pushData() - это функция, которая сохраняет данные в стандартный Dataset. Dataset - это хранилище, спроектированное для хранения данных в табличном формате. Каждый вызов Dataset.pushData() создает новую строку в таблице, где имена свойств выступают в роли заголовков столбцов. В стандартной конфигурации строки представлены в виде JSON-файлов, сохраненных на вашем диске, но Crawlee также поддерживает подключение других систем хранения.
При каждом запуске Crawlee автоматически создается стандартный Dataset, поэтому нет необходимости его инициализировать или создавать экземпляр вручную. Вы можете создавать столько датасетов, сколько нужно, и даже давать им имена. Подробнее об этом можно узнать в руководстве по хранению результатов и в описании функции Dataset.open().
Где найти сохраненные данные
Если вы не меняли локальную конфигурацию Crawlee (что говорило бы о том, что вы уже знаете, что делаете, и это руководство вам не нужно), вы найдете свои данные в директории storage, которую Crawlee создает в рабочей директории запущенного скрипта:
{PROJECT_FOLDER}/storage/datasets/default/
В этой папке будут храниться все ваши сохраненные данные в пронумерованных файлах, в том порядке, в котором они были добавлены в датасет. Каждый файл представляет собой один вызов Dataset.pushData() или одну строку таблицы.
Если вы хотите хранить данные в одном большом файле вместо множества маленьких, ознакомьтесь с разделом о Key-value хранилищах в руководстве по хранению результатов.
Следующие шаги
Далее вы узнаете о некоторых улучшениях, которые можно внести в код вашего краулера, чтобы сделать его более читаемым и удобным для поддержки в долгосрочной перспективе.