← back to Hollywood Import
momentum-recon4.mjs
52 lines
// Recon #4: dump exact DOM contract. (A) one /products grid CARD outerHTML (does it carry
// price + item number in bulk?). (B) Regale detail price-block outerHTML + item number,
// waiting for Livewire price hydration. Read-only. Reuses saved auth.
import { chromium } from 'playwright';
import fs from 'node:fs';
const STATE = new URL('momentum-auth.json', import.meta.url).pathname;
const BASE = 'https://momentumco.com';
const out = {};
const browser = await chromium.launch({ channel: 'chrome', headless: true });
const ctx = await browser.newContext({ storageState: STATE, viewport: { width: 1400, height: 1200 } });
const page = await ctx.newPage();
// (A) grid card
await page.goto(BASE + '/products?forceSync=1', { waitUntil: 'domcontentloaded', timeout: 60000 }).catch(()=>{});
await page.waitForTimeout(6000);
await page.mouse.wheel(0, 3000); await page.waitForTimeout(3000);
out.gridCard = await page.evaluate(() => {
const a = document.querySelector('a[href*="/products/"]');
if (!a) return null;
// climb to the card container
let card = a; for (let i=0;i<5 && card.parentElement;i++){ card = card.parentElement; if ((card.innerText||'').match(/\$\d/)) break; }
return { href: a.getAttribute('href'), cardHasPrice: /\$\d/.test(card.innerText||''),
cardText: (card.innerText||'').replace(/\s+/g,' ').slice(0,400),
cardHTML: card.outerHTML.slice(0, 2500) };
});
// (B) detail with price hydration wait
await page.goto(BASE + '/products/09153923', { waitUntil: 'domcontentloaded', timeout: 60000 }).catch(()=>{});
await page.waitForFunction(() => /\$\s?\d[\d,]*\.\d{2}/.test(document.body.innerText), { timeout: 20000 }).catch(()=>{});
await page.waitForTimeout(2000);
out.detail = await page.evaluate(() => {
// find smallest element containing the per-unit price label
let block = null;
for (const el of document.querySelectorAll('div,section,table,ul')) {
const t = el.innerText || '';
if (/Price\s*:?\s*\$\d/i.test(t) && t.length < 700) { block = el; break; }
}
const body = document.body.innerText;
return {
title: document.title,
itemNumberLine: (body.match(/.{0,30}(item|sku|product)\s*#?.{0,30}/i)||[])[0] || null,
codes: [...new Set((body.match(/\b[A-Z]{2,5}-\d{2,6}\b/g)||[]))].slice(0,12),
priceBlockText: block ? block.innerText.replace(/\n+/g,' | ') : null,
priceBlockHTML: block ? block.outerHTML.slice(0, 2500) : null,
};
});
fs.writeFileSync(new URL('recon4-out.json', import.meta.url), JSON.stringify(out, null, 2));
console.log(JSON.stringify(out, null, 2).slice(0, 4000));
await browser.close();