// Retrieve all matching elements
const productItems = await page.$$('.product-item');
console.log(`Found ${productItems.length} products`);
// Method 1: Iterative processing (recommended)
const productsData = [];
for (const item of productItems) {
const nameElem = await item.$('.name');
const priceElem = await item.$('.price');
const linkElem = await item.$('.link');
const product = {
name: nameElem ? await page.evaluate(el => el.textContent.trim(), nameElem) : '',
price: priceElem ? await page.evaluate(el => el.textContent.trim(), priceElem) : '',
link: linkElem ? await page.evaluate(el => el.href, linkElem) : ''
};
productsData.push(product);
}
// Method 2: Batch processing with evaluate (most efficient)
const productsData = await page.evaluate(() => {
const items = document.querySelectorAll('.product-item');
return Array.from(items).map(item => {
const nameElem = item.querySelector('.name');
const priceElem = item.querySelector('.price');
const linkElem = item.querySelector('.link');
return {
name: nameElem ? nameElem.textContent.trim() : '',
price: priceElem ? priceElem.textContent.trim() : '',
link: linkElem ? linkElem.href : ''
};
});
});
// Method 3: Using map + Promise.all
const productsData = await Promise.all(
productItems.map(async (item) => {
const [name, price, link] = await Promise.all([
item.$eval('.name', el => el.textContent.trim()).catch(() => ''),
item.$eval('.price', el => el.textContent.trim()).catch(() => ''),
item.$eval('.link', el => el.href).catch(() => '')
]);
return { name, price, link };
})
);
// Simplified $$eval usage (uniform structure)
const names = await page.$$eval(
'.product-item .name',
elements => elements.map(el => el.textContent.trim())
);