diff --git a/backend/src/tools/koepi/routes.js b/backend/src/tools/koepi/routes.js index 577ad14..2747257 100644 --- a/backend/src/tools/koepi/routes.js +++ b/backend/src/tools/koepi/routes.js @@ -89,33 +89,35 @@ async function scrapeMarktguru() { }); }); - // Bilder über Node https laden mit Cookies aus dem Browser - const cookies = await page.cookies('https://cdn.marktguru.de'); - const cookieStr = cookies.map(c => `${c.name}=${c.value}`).join('; '); + // 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); - // Sequenziell laden damit Cookie-Session stabil bleibt - for (const offer of offers) { await new Promise(resolve => { - if (!offer.image || !offer.image.startsWith('https://')) return resolve(); - const req = require('https').get(offer.image, { - headers: { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', - 'Referer': 'https://www.marktguru.de/', - 'Cookie': cookieStr, + for (const offer of offers) { + if (offer.image && b64Images[offer.image]) { + offer.image = b64Images[offer.image]; + } else { + offer.image = null; } - }, res => { - if (res.statusCode !== 200) { offer.image = null; return resolve(); } - const chunks = []; - res.on('data', c => chunks.push(c)); - res.on('end', () => { - const b64 = Buffer.concat(chunks).toString('base64'); - const mime = res.headers['content-type'] || 'image/webp'; - offer.image = `data:${mime};base64,${b64}`; - resolve(); - }); - }); - req.on('error', () => { offer.image = null; resolve(); }); - req.setTimeout(8000, () => { req.destroy(); offer.image = null; resolve(); }); - }); } + } + } // Filtern auf Ziel-Händler + nur König Pilsener const filtered = offers.filter(o => { diff --git a/frontend/src/tools/koepi.jsx b/frontend/src/tools/koepi.jsx index 2fbdbe1..37dafa6 100644 --- a/frontend/src/tools/koepi.jsx +++ b/frontend/src/tools/koepi.jsx @@ -36,9 +36,9 @@ function OfferCard({ offer }) { }}> {/* Bild oben, volle Breite */} {offer.image && ( -
+
König Pilsener { e.target.parentElement.style.display='none'; }} />