const puppeteer = require('puppeteer-extra'); async function scrapeGoogleShopping(query, browser) { const page = await browser.newPage(); const url = `https://www.google.com/search?q=${encodeURIComponent(query)}&tbm=shop`; try { await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 }); const products = await page.evaluate(() => { const results = []; // Google Shopping results are often inside blocks with class .sh-dgr__grid-result or similar const cards = document.querySelectorAll('.sh-dgr__grid-result, .sh-np__click-target'); cards.forEach(card => { const titleEl = card.querySelector('h3, [role="heading"]'); const priceEl = card.querySelector('.a80p0, [data-price], span[aria-hidden="true"]:not(:empty)'); // Fallback for price: look for any element mimicking a price format let priceText = null; if (priceEl) { priceText = priceEl.innerText.trim(); } else { const spans = card.querySelectorAll('span'); spans.forEach(span => { if (span.innerText.includes('€') || span.innerText.match(/\d+,\d{2}/)) { priceText = span.innerText.trim(); } }); } const linkEl = card.tagName === 'A' ? card : card.querySelector('a'); if (titleEl && priceText) { results.push({ name: titleEl.innerText.trim(), price: priceText, link: linkEl ? linkEl.href : null, source: 'Google Shopping' }); } }); return results.slice(0, 5); }); return products; } catch (error) { console.error(`[Google Shopping] Error scraping ${query}:`, error.message); return []; } finally { await page.close(); } } module.exports = scrapeGoogleShopping;