← back to Eur Recrawl

probe-images.mjs

30 lines

// probe-images.mjs <product-url> [engine] — dump product image URLs from a front-end page.
import { chromium, webkit } from 'playwright';
import path from 'node:path';
const url = process.argv[2];
const ENGINE = (process.argv[3] || 'webkit').toLowerCase();
if (!url) { console.error('usage: node probe-images.mjs <url> [chrome|webkit]'); process.exit(1); }
const drv = ENGINE === 'webkit' ? webkit : chromium;
const opts = { headless: false, viewport: { width: 1440, height: 900 } };
if (ENGINE === 'chrome') opts.channel = 'chrome';
const ctx = await drv.launchPersistentContext(path.join(process.cwd(), '.auth', `dg-${ENGINE}`), opts);
const page = ctx.pages()[0] || await ctx.newPage();
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 }).catch((e) => console.log('nav', e.message));
await page.waitForTimeout(5000);
const out = await page.evaluate(() => {
  const abs = (s) => { try { return new URL(s, location.href).href; } catch { return s; } };
  const srcs = new Set();
  for (const img of document.querySelectorAll('img')) {
    for (const a of [img.src, img.getAttribute('data-src'), img.getAttribute('data-lazy'), (img.srcset || '').split(',').pop()?.trim().split(' ')[0]]) if (a) srcs.add(abs(a));
  }
  // also swatch/colorway thumbnails often carry a data attr
  const sw = [...document.querySelectorAll('[data-image],[data-zoom-image],[data-large]')].map((e) => abs(e.getAttribute('data-image') || e.getAttribute('data-zoom-image') || e.getAttribute('data-large')));
  const prod = [...srcs, ...sw].filter((s) => /product|pattern|media|asset|catalog|cdn|image/i.test(s) && !/logo|icon|sprite|flag|placeholder|blank/i.test(s));
  return { title: document.title, all: srcs.size, product: [...new Set(prod)].slice(0, 25) };
});
console.log('title:', out.title.slice(0, 60));
console.log('total imgs:', out.all, '| product-ish:', out.product.length);
out.product.forEach((s) => console.log('  ' + s));
await page.waitForTimeout(1000);
await ctx.close();