chore: bump task worker version comment
Force new git SHA to avoid CI scientific notation bug. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
183
backend/scripts/test-treez-brands-detailed.ts
Normal file
183
backend/scripts/test-treez-brands-detailed.ts
Normal file
@@ -0,0 +1,183 @@
|
||||
/**
|
||||
* Detailed brand section analysis
|
||||
*/
|
||||
|
||||
import puppeteer, { Page } from 'puppeteer';
|
||||
|
||||
const STORE_ID = 'best';
|
||||
|
||||
async function sleep(ms: number): Promise<void> {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function bypassAgeGate(page: Page): Promise<void> {
|
||||
const ageGate = await page.$('[data-testid="age-gate-modal"]');
|
||||
if (ageGate) {
|
||||
console.log(' Age gate detected, bypassing...');
|
||||
const btn = await page.$('[data-testid="age-gate-submit-button"]');
|
||||
if (btn) await btn.click();
|
||||
await sleep(2000);
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('='.repeat(60));
|
||||
console.log('Detailed Brand Section Analysis');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
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`;
|
||||
console.log(`\nNavigating to ${url}`);
|
||||
|
||||
await page.goto(url, { waitUntil: 'networkidle2', timeout: 60000 });
|
||||
await sleep(3000);
|
||||
await bypassAgeGate(page);
|
||||
await sleep(2000);
|
||||
|
||||
// Scroll multiple times to load all content
|
||||
console.log('\n[1] Scrolling to load all content...');
|
||||
let previousHeight = 0;
|
||||
let scrollCount = 0;
|
||||
|
||||
for (let i = 0; i < 30; i++) {
|
||||
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
|
||||
await sleep(1500);
|
||||
|
||||
const currentHeight = await page.evaluate(() => document.body.scrollHeight);
|
||||
const productCount = await page.evaluate(() =>
|
||||
document.querySelectorAll('a[href*="/product/"]').length
|
||||
);
|
||||
|
||||
console.log(` Scroll ${i + 1}: height=${currentHeight}, products=${productCount}`);
|
||||
|
||||
if (currentHeight === previousHeight) {
|
||||
scrollCount++;
|
||||
if (scrollCount >= 3) break;
|
||||
} else {
|
||||
scrollCount = 0;
|
||||
}
|
||||
previousHeight = currentHeight;
|
||||
}
|
||||
|
||||
// Look at ALL h2/h3 headers on page
|
||||
console.log('\n[2] Finding ALL h2/h3 headers on page...');
|
||||
|
||||
const headers = await page.evaluate(() => {
|
||||
const results: { tag: string; text: string; parentClass: string }[] = [];
|
||||
|
||||
document.querySelectorAll('h2, h3').forEach((el: Element) => {
|
||||
results.push({
|
||||
tag: el.tagName,
|
||||
text: el.textContent?.trim().slice(0, 80) || '',
|
||||
parentClass: el.parentElement?.className?.slice(0, 50) || '',
|
||||
});
|
||||
});
|
||||
|
||||
return results;
|
||||
});
|
||||
|
||||
console.log(`Found ${headers.length} headers:`);
|
||||
headers.forEach((h: { tag: string; text: string }) =>
|
||||
console.log(` [${h.tag}] "${h.text}"`)
|
||||
);
|
||||
|
||||
// Get products grouped by their section heading
|
||||
console.log('\n[3] Getting products per section...');
|
||||
|
||||
const sectionProducts = await page.evaluate(() => {
|
||||
const results: { heading: string; products: number }[] = [];
|
||||
|
||||
// Find all sections that contain products
|
||||
document.querySelectorAll('[class*="products_product__section"]').forEach((section: Element) => {
|
||||
const heading = section.querySelector('h2, h3');
|
||||
const headingText = heading?.textContent?.trim() || 'Unknown';
|
||||
const products = section.querySelectorAll('a[href*="/product/"]');
|
||||
|
||||
results.push({
|
||||
heading: headingText,
|
||||
products: products.length,
|
||||
});
|
||||
});
|
||||
|
||||
return results;
|
||||
});
|
||||
|
||||
console.log(`Found ${sectionProducts.length} brand sections:`);
|
||||
let totalProducts = 0;
|
||||
sectionProducts.forEach((s: { heading: string; products: number }) => {
|
||||
console.log(` ${s.heading}: ${s.products} products`);
|
||||
totalProducts += s.products;
|
||||
});
|
||||
console.log(`\nTotal products across all sections: ${totalProducts}`);
|
||||
|
||||
// Also extract brand from each product's URL/card
|
||||
console.log('\n[4] Extracting brand from product URLs/cards...');
|
||||
|
||||
const brandCounts = await page.evaluate(() => {
|
||||
const byBrand: Record<string, number> = {};
|
||||
const seen = new Set<string>();
|
||||
|
||||
document.querySelectorAll('a[href*="/product/"]').forEach((a: Element) => {
|
||||
const href = a.getAttribute('href') || '';
|
||||
const img = a.querySelector('img');
|
||||
const name = img?.getAttribute('alt') || '';
|
||||
|
||||
if (!name || seen.has(name)) return;
|
||||
seen.add(name);
|
||||
|
||||
// Try to find brand from the card
|
||||
const brandEl = a.querySelector('[class*="brand"], [class*="Brand"], span, p');
|
||||
let brand = '';
|
||||
|
||||
// Try various methods to find brand
|
||||
const allSpans = a.querySelectorAll('span, p');
|
||||
allSpans.forEach((span: Element) => {
|
||||
const text = span.textContent?.trim() || '';
|
||||
if (text && text.length < 50 && text !== name && !text.includes('$')) {
|
||||
if (!brand) brand = text;
|
||||
}
|
||||
});
|
||||
|
||||
// Fallback: get brand from parent section heading
|
||||
if (!brand) {
|
||||
const section = a.closest('[class*="products_product__section"]');
|
||||
const heading = section?.querySelector('h2, h3');
|
||||
brand = heading?.textContent?.trim() || 'Unknown';
|
||||
}
|
||||
|
||||
byBrand[brand] = (byBrand[brand] || 0) + 1;
|
||||
});
|
||||
|
||||
return byBrand;
|
||||
});
|
||||
|
||||
console.log('Products by brand:');
|
||||
Object.entries(brandCounts)
|
||||
.sort((a, b) => (b[1] as number) - (a[1] as number))
|
||||
.forEach(([brand, count]) => {
|
||||
console.log(` ${brand}: ${count}`);
|
||||
});
|
||||
|
||||
const uniqueTotal = Object.values(brandCounts).reduce((sum: number, c) => sum + (c as number), 0);
|
||||
console.log(`\nTotal unique products: ${uniqueTotal}`);
|
||||
|
||||
await browser.close();
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
Reference in New Issue
Block a user