diff --git a/backend/src/tools/koepi/routes.js b/backend/src/tools/koepi/routes.js index 2747257..b941cac 100644 --- a/backend/src/tools/koepi/routes.js +++ b/backend/src/tools/koepi/routes.js @@ -89,34 +89,20 @@ async function scrapeMarktguru() { }); }); - // Bilder alle auf einmal im Browser-Kontext laden (hat Zugriff auf CDN) - const imageUrls = offers.map(o => o.image).filter(Boolean); - if (imageUrls.length > 0) { - const b64Images = await page.evaluate(async (urls) => { - const results = {}; - await Promise.all(urls.map(async url => { - try { - const resp = await fetch(url); - if (!resp.ok) { results[url] = null; return; } - const blob = await resp.blob(); - results[url] = await new Promise(res => { - const r = new FileReader(); - r.onloadend = () => res(r.result); - r.onerror = () => res(null); - r.readAsDataURL(blob); - }); - } catch { results[url] = null; } - })); - return results; - }, imageUrls); - - for (const offer of offers) { - if (offer.image && b64Images[offer.image]) { - offer.image = b64Images[offer.image]; - } else { - offer.image = null; - } - } + // Bilder via Puppeteer screenshot der img-Elemente + const imgElements = await page.$$('img.offer-list-item-img'); + for (let i = 0; i < offers.length; i++) { + if (!offers[i].image || !imgElements[i]) continue; + try { + // Warte bis Bild geladen + await page.evaluate(el => new Promise(res => { + if (el.complete) return res(); + el.onload = res; el.onerror = res; + setTimeout(res, 3000); + }), imgElements[i]); + const b64 = await imgElements[i].screenshot({ encoding: 'base64' }); + offers[i].image = b64 ? `data:image/png;base64,${b64}` : null; + } catch { offers[i].image = null; } } // Filtern auf Ziel-Händler + nur König Pilsener