fix: KoePi Adress-Extraktion robuster (Position statt DOM-Nachbarschaft) + Tiefen-Diagnose bei Fehlschlag

This commit is contained in:
2026-07-12 15:01:04 +02:00
parent c85b29910c
commit af208be95b

View File

@@ -137,13 +137,35 @@ async function scrapeMarktguru(forceRefresh = false) {
const img = card.querySelector('img.offer-list-item-img'); const img = card.querySelector('img.offer-list-item-img');
const badge = card.querySelector('.badge, .discount-badge')?.textContent?.trim() || ''; const badge = card.querySelector('.badge, .discount-badge')?.textContent?.trim() || '';
const imgSrc = img?.src?.replace('/medium.webp', '/large.webp') || img?.src || null; const imgSrc = img?.src?.replace('/medium.webp', '/large.webp') || img?.src || null;
const retailerDd = card.querySelector('dd.retailer-name'); // Adresse steht bei marktguru direkt nach dem Händlernamen, aber nicht
const addressDd = retailerDd?.nextElementSibling?.tagName === 'DD' ? retailerDd.nextElementSibling : null; // zwingend als direktes DOM-Geschwisterelement (z.B. wenn dazwischen
const realAddress = addressDd?.textContent?.trim() || ''; // noch ein <dt>-Label liegt) — daher über die Position in der Liste
// ALLER <dd>-Elemente der Karte suchen statt über nextElementSibling
const allDds = Array.from(card.querySelectorAll('dd'));
const retailerIdx = allDds.findIndex(d => d.classList.contains('retailer-name'));
let realAddress = '';
if (retailerIdx !== -1 && allDds[retailerIdx + 1]) {
const next = allDds[retailerIdx + 1];
const isOtherField = next.classList.contains('valid') || next.classList.contains('time-left');
if (!isOtherField) realAddress = next.textContent?.trim() || '';
}
return { name, brand, price, oldPrice, retailer, dateRange, validity, description, badge, address: '', realAddress, image: imgSrc }; return { name, brand, price, oldPrice, retailer, dateRange, validity, description, badge, address: '', realAddress, image: imgSrc };
}); });
}); });
// Einmalige Tiefen-Diagnose: rohe dd-Struktur der ersten Karte, falls die
// Adress-Extraktion (oben) leer bleibt und wir den echten Aufbau brauchen
if (offers.length && !offers[0].realAddress) {
const rawDdDump = await page.evaluate(() => {
const card = document.querySelector('li.offer-list-item');
if (!card) return 'kein Angebot-Element gefunden';
return Array.from(card.querySelectorAll('dt, dd'))
.map(el => `<${el.tagName.toLowerCase()} class="${el.className}">${el.textContent.trim().slice(0,60)}</${el.tagName.toLowerCase()}>`)
.join('\n ');
});
console.log('🍺 KöPi RAW dt/dd-Struktur der ersten Karte (Adresse war leer):\n ' + rawDdDump);
}
// Lokale Bilder auswählen basierend auf Beschreibung // Lokale Bilder auswählen basierend auf Beschreibung
for (const offer of offers) { for (const offer of offers) {
const desc = (offer.description || '').toLowerCase(); const desc = (offer.description || '').toLowerCase();