/** * Analyze all product element structures to find all selector patterns */ 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('Analyzing Treez product selectors...\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); // Analyze product elements const analysis = await page.evaluate(() => { const products = document.querySelectorAll('[class*="product_product__"]'); const results: { hasName: number; hasPrice: number; noName: number; noPrice: number; nameClasses: Record; priceClasses: Record; sampleNoNameHTML: string[]; sampleWithNameHTML: string[]; h5Count: number; h4Count: number; h3Count: number; allHeadingsWithName: number; } = { hasName: 0, hasPrice: 0, noName: 0, noPrice: 0, nameClasses: {}, priceClasses: {}, sampleNoNameHTML: [], sampleWithNameHTML: [], h5Count: 0, h4Count: 0, h3Count: 0, allHeadingsWithName: 0, }; products.forEach((el, i) => { // Check current selectors const nameEl = el.querySelector('[class*="product__name"], [class*="name__"]'); const priceEl = el.querySelector('[class*="price"]'); if (nameEl) { results.hasName++; const cls = nameEl.className?.toString?.() || ''; results.nameClasses[cls] = (results.nameClasses[cls] || 0) + 1; } else { results.noName++; if (results.sampleNoNameHTML.length < 3) { results.sampleNoNameHTML.push(el.innerHTML.slice(0, 500)); } } if (priceEl) { results.hasPrice++; } else { results.noPrice++; } // Check for headings that might contain names const h5 = el.querySelector('h5'); const h4 = el.querySelector('h4'); const h3 = el.querySelector('h3'); if (h5) results.h5Count++; if (h4) results.h4Count++; if (h3) results.h3Count++; // Any heading with text const anyHeading = el.querySelector('h1, h2, h3, h4, h5, h6'); if (anyHeading?.textContent?.trim()) { results.allHeadingsWithName++; } }); return results; }); console.log('Product Analysis:'); console.log(`Total products: ${analysis.hasName + analysis.noName}`); console.log(`With name (current selector): ${analysis.hasName}`); console.log(`Without name (current selector): ${analysis.noName}`); console.log(`With price: ${analysis.hasPrice}`); console.log(`\nHeading counts:`); console.log(` H5: ${analysis.h5Count}`); console.log(` H4: ${analysis.h4Count}`); console.log(` H3: ${analysis.h3Count}`); console.log(` Any heading with text: ${analysis.allHeadingsWithName}`); console.log('\nName classes found:'); Object.entries(analysis.nameClasses).forEach(([cls, count]) => { console.log(` (${count}x) ${cls.slice(0, 80)}`); }); console.log('\n--- Sample products WITHOUT name selector ---'); analysis.sampleNoNameHTML.forEach((html, i) => { console.log(`\n[Sample ${i + 1}]:`); console.log(html); }); // Try different selectors console.log('\n\n--- Testing alternative selectors ---'); const altResults = await page.evaluate(() => { const products = document.querySelectorAll('[class*="product_product__"]'); const tests: Record = {}; const selectors = [ 'h5', 'h4', 'h3', '[class*="heading"]', '[class*="title"]', '[class*="name"]', 'a[href*="/product/"]', '.product_product__name__JcEk0', '[class*="ProductCard"]', ]; selectors.forEach(sel => { let count = 0; products.forEach(el => { if (el.querySelector(sel)) count++; }); tests[sel] = count; }); return tests; }); Object.entries(altResults).forEach(([sel, count]) => { console.log(` ${sel}: ${count} products`); }); await browser.close(); } main().catch(console.error);