fix: KöPi - alle Bilder im Browser-Kontext laden, dunkler Hintergrund
This commit is contained in:
@@ -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 => {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user