← back to Dw Marketing Reels
harvest-ol-family.cjs
83 lines
'use strict';
// Harvest real product image URLs for the blocked O&L-family vendors (osborneandlittle.com,
// designersguild.com) via ONE Browserbase cloud session (residential IP bypasses the local block).
// For each target: goto known product_url OR run the site's own search by mfr_sku, then read
// og:image + product-gallery <img> srcs. Prints JSON. Does NOT download (curl-download the URLs
// afterward from this box — the CDN image hosts are reachable even when the html host isn't).
const os = require('os'), fs = require('fs');
require('dotenv').config({ path: os.homedir() + '/.claude/skills/browserbase/.env' });
const Browserbase = require('@browserbasehq/sdk').default;
const { chromium } = require('playwright-core');
const sleep = ms => new Promise(r => setTimeout(r, ms));
// targets: {sku, pattern, url? , searchUrl?}
const OL = 'https://www.osborneandlittle.com';
const targets = [
{ sku:'W7814-01', pattern:'Colonnato', url:`${OL}/colonnato-w7814.html` },
{ sku:'W7682-01', pattern:'Coralline', url:`${OL}/coralline-w7682.html` },
{ sku:'W7024-03', pattern:'Japanese Garden', url:`${OL}/japanese-garden-w7024-w7024.html` },
{ sku:'W6541-02', pattern:'Peacock', url:`${OL}/peacock-w6541.html` },
{ sku:'W5223-03', pattern:'Tamba', url:`${OL}/tamba-w5223.html` },
{ sku:'W7334-1', pattern:'Trailing Orchid', search:`${OL}/catalogsearch/result/?q=W7334` },
{ sku:'EUR-70328',pattern:'Audley', search:`${OL}/catalogsearch/result/?q=Audley` },
{ sku:'EUR-70402',pattern:'Canestra', search:`${OL}/catalogsearch/result/?q=Canestra` },
{ sku:'EUR-70351',pattern:'Chameleon', search:`${OL}/catalogsearch/result/?q=Chameleon` },
{ sku:'PDG1062-01',pattern:'Surimono', search:`https://www.designersguild.com/uk/search?q=Surimono`, vendor:'DG' },
{ sku:'NCW4270-03',pattern:'Coromandel', search:`${OL}/catalogsearch/result/?q=NCW4270`, vendor:'NC' },
{ sku:'NCW4270-05',pattern:'Coromandel', search:`${OL}/catalogsearch/result/?q=NCW4270`, vendor:'NC' },
];
async function readImgs(page){
return await page.evaluate(() => {
const out = { og:null, gallery:[], title:document.title };
const og = document.querySelector('meta[property="og:image"]');
if (og) out.og = og.content;
// magento gallery
document.querySelectorAll('img').forEach(im => {
const s = im.src || im.getAttribute('data-src') || '';
if (/media\/catalog\/product|\/product\//i.test(s) && !/AVATAR|logo|placeholder/i.test(s)) out.gallery.push(s);
});
// magento JSON gallery in script
const m = document.body.innerHTML.match(/"data":\s*\[\s*\{[^\]]*?"img":"([^"]+)"/);
if (m) out.galleryJson = m[1].replace(/\\\//g,'/');
return out;
});
}
(async () => {
const bb = new Browserbase({ apiKey: process.env.BROWSERBASE_API_KEY });
const session = await bb.sessions.create({ projectId: process.env.BROWSERBASE_PROJECT_ID, browserSettings: { solveCaptchas: true } });
console.error('session', session.id, 'debug:', session.debuggerUrl || '');
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0].pages()[0] || await browser.contexts()[0].newPage();
page.setDefaultTimeout(45000);
const results = [];
for (const t of targets){
const r = { sku:t.sku, pattern:t.pattern, vendor:t.vendor||'OL' };
try {
if (t.url){
await page.goto(t.url, { waitUntil:'domcontentloaded' }).catch(()=>{});
await sleep(2500);
if (/404|not found|page not found/i.test(await page.title())) { r.note='url-404, trying pattern search'; }
}
if (!t.url || (r.note && t.search)) {
if (t.search){ await page.goto(t.search, { waitUntil:'domcontentloaded' }).catch(()=>{}); await sleep(2500);
// click first product result
const link = await page.$('a.product-item-link, .product-item a[href*=".html"], a.product-item-photo, .product-item-info a');
if (link){ const href = await link.getAttribute('href'); r.resolvedUrl=href; await page.goto(href,{waitUntil:'domcontentloaded'}).catch(()=>{}); await sleep(2500); }
else r.note = (r.note?r.note+'; ':'') + 'no search result';
}
}
r.finalUrl = page.url();
const imgs = await readImgs(page);
r.pageTitle = imgs.title; r.og = imgs.og; r.gallery = [...new Set(imgs.gallery)].slice(0,6); r.galleryJson = imgs.galleryJson;
} catch(e){ r.error = e.message; }
console.error(`[${r.sku}] ${r.finalUrl||''} og=${r.og?'Y':'N'} gal=${(r.gallery||[]).length}`);
results.push(r);
}
await browser.close().catch(()=>{});
const fp = os.homedir()+'/Projects/dw-marketing-reels/harvest-ol-results.json';
fs.writeFileSync(fp, JSON.stringify(results,null,2));
console.log(fp);
})().catch(e=>{ console.error('FATAL', e.message); process.exit(1); });