본문으로 건너뛰기

데이터 저장하기

데이터 추출 작업에서 가장 중요한 것은 추출한 데이터를 나중에 사용하고 처리할 수 있도록 저장하는 것입니다. 이제 이 튜토리얼의 마지막이자 가장 중요한 부분에 도달했으니 주의 깊게 살펴보시기 바랍니다!

먼저 파일 상단에 새로운 import문을 추가하세요:

import { PlaywrightCrawler, Dataset } from 'crawlee';

그런 다음 console.log(results) 호출을 다음과 같이 변경하세요:

await Dataset.pushData(results);

이게 전부입니다. 이전과 달리 이번에는 진지하게 말씀드립니다. 이것으로 끝입니다. 최종 코드는 다음과 같습니다:

Run on
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의 자동 데이터셋 초기화

Crawlee를 시작할 때마다 기본 Dataset이 자동으로 생성되므로, 별도로 초기화하거나 인스턴스를 생성할 필요가 없습니다. 원하는 만큼 데이터셋을 만들고 이름을 지정할 수 있습니다. 자세한 내용은 결과 저장소 가이드Dataset.open() 함수를 참조하세요.

저장된 데이터 찾기

Crawlee의 로컬 설정을 변경하지 않았다면(변경했다면 이 튜토리얼이 필요 없었을 것입니다), 실행 중인 스크립트의 작업 디렉토리에 Crawlee가 생성하는 storage 디렉토리에서 데이터를 찾을 수 있습니다:

{PROJECT_FOLDER}/storage/datasets/default/

위 폴더에는 데이터셋에 저장된 순서대로 번호가 매겨진 파일들이 있습니다. 각 파일은 Dataset.pushData()를 한 번 호출한 결과 또는 하나의 테이블 행을 나타냅니다.

단일 파일 데이터 저장 옵션

데이터를 여러 개의 작은 파일 대신 하나의 큰 파일로 저장하고 싶다면, 결과 저장소 가이드에서 Key-value 저장소 부분을 참조하세요.

다음 단계

다음으로는 크롤러 코드를 더 읽기 쉽고 장기적으로 유지보수하기 쉽게 만드는 방법을 살펴보겠습니다.