fix: KöPi - alle Bilder im Browser-Kontext laden, dunkler Hintergrund

This commit is contained in:
2026-07-09 10:57:33 +02:00
parent 682d79b42d
commit 2f3368a7e3
2 changed files with 29 additions and 27 deletions

View File

@@ -89,33 +89,35 @@ async function scrapeMarktguru() {
}); });
}); });
// Bilder über Node https laden mit Cookies aus dem Browser // Bilder alle auf einmal im Browser-Kontext laden (hat Zugriff auf CDN)
const cookies = await page.cookies('https://cdn.marktguru.de'); const imageUrls = offers.map(o => o.image).filter(Boolean);
const cookieStr = cookies.map(c => `${c.name}=${c.value}`).join('; '); 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) {
for (const offer of offers) { await new Promise(resolve => { if (offer.image && b64Images[offer.image]) {
if (!offer.image || !offer.image.startsWith('https://')) return resolve(); offer.image = b64Images[offer.image];
const req = require('https').get(offer.image, { } else {
headers: { offer.image = null;
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', }
'Referer': 'https://www.marktguru.de/', }
'Cookie': cookieStr,
} }
}, 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 // Filtern auf Ziel-Händler + nur König Pilsener
const filtered = offers.filter(o => { const filtered = offers.filter(o => {

View File

@@ -36,9 +36,9 @@ function OfferCard({ offer }) {
}}> }}>
{/* Bild oben, volle Breite */} {/* Bild oben, volle Breite */}
{offer.image && ( {offer.image && (
<div style={{ margin:'-12px -14px 8px -14px', height:160, background:'#f0f0f0', borderRadius:'8px 8px 0 0', overflow:'hidden', display:'flex', alignItems:'center', justifyContent:'center' }}> <div style={{ margin:'-12px -14px 8px -14px', height:180, background:'#111', borderRadius:'8px 8px 0 0', overflow:'hidden', display:'flex', alignItems:'center', justifyContent:'center' }}>
<img src={offer.image} alt="König Pilsener" <img src={offer.image} alt="König Pilsener"
style={{ width:'100%', height:'100%', objectFit:'contain' }} style={{ maxWidth:'100%', maxHeight:'100%', objectFit:'contain' }}
onError={e => { e.target.parentElement.style.display='none'; }} onError={e => { e.target.parentElement.style.display='none'; }}
/> />
</div> </div>