/** * Find the correct product card container selector */ import puppeteer, { Page } from 'puppeteer'; const STORE_ID = 'best'; async function sleep(ms: number): Promise { return new Promise(resolve => setTimeout(resolve, ms)); } async function bypassAgeGate(page: Page): Promise { const ageGate = await page.$('[data-testid="age-gate-modal"]'); if (ageGate) { const btn = await page.$('[data-testid="age-gate-submit-button"]'); if (btn) await btn.click(); await sleep(2000); } } async function main() { console.log('Finding Treez product card containers...\n'); const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'], }); const page = await browser.newPage(); await page.setViewport({ width: 1920, height: 1080 }); await page.setRequestInterception(true); page.on('request', (req) => { if (['image', 'font', 'media'].includes(req.resourceType())) { req.abort(); } else { req.continue(); } }); const url = `https://${STORE_ID}.treez.io/onlinemenu/brands?customerType=ADULT`; await page.goto(url, { waitUntil: 'networkidle2', timeout: 60000 }); await sleep(3000); await bypassAgeGate(page); await sleep(2000); // Find product card containers by looking for elements that contain both name AND price const analysis = await page.evaluate(() => { // Strategy: find all H5 elements (which contain names), then get their parent containers const nameElements = document.querySelectorAll('h5.product_product__name__JcEk0'); const containers: Map = new Map(); nameElements.forEach(nameEl => { // Walk up to find the product card container let current = nameEl.parentElement; let depth = 0; while (current && depth < 10) { const className = current.className?.toString?.() || ''; // Look for ProductCard in the class name if (className.includes('ProductCard')) { const key = className.slice(0, 100); const existing = containers.get(key) || { count: 0, sample: '' }; existing.count++; if (!existing.sample) { existing.sample = current.outerHTML.slice(0, 300); } containers.set(key, existing); break; } current = current.parentElement; depth++; } }); return Array.from(containers.entries()).map(([cls, data]) => ({ class: cls, count: data.count, sample: data.sample, })); }); console.log('Product card containers found:'); analysis.forEach(({ class: cls, count, sample }) => { console.log(`\n[${count}x] ${cls}`); console.log(`Sample: ${sample.slice(0, 200)}...`); }); // Now test various container selectors console.log('\n\n--- Testing container selectors ---'); const selectorTests = await page.evaluate(() => { const tests: Record = {}; const selectors = [ '[class*="ProductCardWithBtn"]', '[class*="ProductCard_product"]', '[class*="ProductCard__"]', 'article[class*="product"]', 'div[class*="ProductCard"]', 'a[class*="ProductCard"]', '[class*="product_product__"][class*="link"]', 'article', ]; selectors.forEach(sel => { const elements = document.querySelectorAll(sel); let withName = 0; let withPrice = 0; elements.forEach(el => { if (el.querySelector('h5, [class*="product__name"]')) withName++; if (el.querySelector('[class*="price"]')) withPrice++; }); tests[sel] = { total: elements.length, withName, withPrice }; }); return tests; }); Object.entries(selectorTests).forEach(([sel, { total, withName, withPrice }]) => { console.log(`${sel}: ${total} total, ${withName} with name, ${withPrice} with price`); }); // Get the actual product card class pattern console.log('\n\n--- Finding exact product card class ---'); const exactClasses = await page.evaluate(() => { // Find elements that have both h5 name AND price child const allElements = document.querySelectorAll('*'); const matches: { tag: string; class: string }[] = []; allElements.forEach(el => { const hasName = el.querySelector('h5.product_product__name__JcEk0'); const hasPrice = el.querySelector('[class*="price__ins"], [class*="price__"]'); if (hasName && hasPrice) { const className = el.className?.toString?.() || ''; if (className && !matches.some(m => m.class === className)) { matches.push({ tag: el.tagName, class: className.slice(0, 150) }); } } }); return matches; }); console.log('Elements containing both name and price:'); exactClasses.forEach(({ tag, class: cls }) => { console.log(` [${tag}] ${cls}`); }); await browser.close(); } main().catch(console.error);