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>
131 lines
3.8 KiB
TypeScript
131 lines
3.8 KiB
TypeScript
import puppeteer from 'puppeteer';
|
|
|
|
async function sleep(ms: number): Promise<void> {
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
}
|
|
|
|
async function main() {
|
|
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();
|
|
}
|
|
});
|
|
|
|
await page.goto('https://shop.bestdispensary.com/brands', {
|
|
waitUntil: 'networkidle2',
|
|
timeout: 60000
|
|
});
|
|
await sleep(3000);
|
|
|
|
// Bypass age gate
|
|
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);
|
|
}
|
|
|
|
// Use the selector hint: /html/body/main/section
|
|
console.log('Looking at main > section structure...\n');
|
|
|
|
const sectionInfo = await page.evaluate(() => {
|
|
const main = document.querySelector('main');
|
|
if (!main) return { error: 'No main element' };
|
|
|
|
const sections = main.querySelectorAll('section');
|
|
const results: any[] = [];
|
|
|
|
sections.forEach((section, i) => {
|
|
const children = section.children;
|
|
const childInfo: string[] = [];
|
|
|
|
for (let j = 0; j < Math.min(children.length, 10); j++) {
|
|
const child = children[j];
|
|
childInfo.push(child.tagName + '.' + (child.className?.slice(0, 30) || ''));
|
|
}
|
|
|
|
results.push({
|
|
index: i,
|
|
class: section.className?.slice(0, 50),
|
|
childCount: children.length,
|
|
sampleChildren: childInfo,
|
|
});
|
|
});
|
|
|
|
return results;
|
|
});
|
|
|
|
console.log('Sections in main:');
|
|
console.log(JSON.stringify(sectionInfo, null, 2));
|
|
|
|
// Look for brand cards within the section
|
|
console.log('\nLooking for brand cards in main > section...');
|
|
|
|
const brandCards = await page.evaluate(() => {
|
|
const section = document.querySelector('main > section');
|
|
if (!section) return [];
|
|
|
|
// Get all child elements that might be brand cards
|
|
const cards: { tag: string; text: string; href: string }[] = [];
|
|
|
|
section.querySelectorAll('a').forEach((a: Element) => {
|
|
const href = a.getAttribute('href') || '';
|
|
const text = a.textContent?.trim().slice(0, 50) || '';
|
|
cards.push({ tag: 'a', text, href });
|
|
});
|
|
|
|
return cards;
|
|
});
|
|
|
|
console.log(`Found ${brandCards.length} links in section:`);
|
|
brandCards.slice(0, 30).forEach(c => console.log(` ${c.text} -> ${c.href}`));
|
|
|
|
// Get the grid of brand cards
|
|
console.log('\nLooking for grid container...');
|
|
|
|
const gridCards = await page.evaluate(() => {
|
|
// Look for grid-like containers
|
|
const grids = document.querySelectorAll('[class*="grid"], [class*="Grid"], main section > div');
|
|
const results: any[] = [];
|
|
|
|
grids.forEach((grid, i) => {
|
|
const links = grid.querySelectorAll('a[href*="/brand/"]');
|
|
if (links.length > 5) {
|
|
const brands: string[] = [];
|
|
links.forEach((a: Element) => {
|
|
const text = a.textContent?.trim().split('\n')[0] || '';
|
|
if (text && !brands.includes(text)) brands.push(text);
|
|
});
|
|
results.push({
|
|
class: grid.className?.slice(0, 40),
|
|
brandCount: brands.length,
|
|
brands: brands.slice(0, 50),
|
|
});
|
|
}
|
|
});
|
|
|
|
return results;
|
|
});
|
|
|
|
console.log('Grid containers with brands:');
|
|
gridCards.forEach(g => {
|
|
console.log(`\n[${g.brandCount} brands] class="${g.class}"`);
|
|
g.brands.forEach((b: string, i: number) => console.log(` ${i+1}. ${b}`));
|
|
});
|
|
|
|
await browser.close();
|
|
}
|
|
|
|
main().catch(console.error);
|