diff --git a/backend/src/tools/koepi/routes.js b/backend/src/tools/koepi/routes.js
index e9995ca..c8c8f01 100644
--- a/backend/src/tools/koepi/routes.js
+++ b/backend/src/tools/koepi/routes.js
@@ -137,13 +137,35 @@ async function scrapeMarktguru(forceRefresh = false) {
const img = card.querySelector('img.offer-list-item-img');
const badge = card.querySelector('.badge, .discount-badge')?.textContent?.trim() || '';
const imgSrc = img?.src?.replace('/medium.webp', '/large.webp') || img?.src || null;
- const retailerDd = card.querySelector('dd.retailer-name');
- const addressDd = retailerDd?.nextElementSibling?.tagName === 'DD' ? retailerDd.nextElementSibling : null;
- const realAddress = addressDd?.textContent?.trim() || '';
+ // Adresse steht bei marktguru direkt nach dem Händlernamen, aber nicht
+ // zwingend als direktes DOM-Geschwisterelement (z.B. wenn dazwischen
+ // noch ein
-Label liegt) — daher über die Position in der Liste
+ // ALLER -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 };
});
});
+ // 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
for (const offer of offers) {
const desc = (offer.description || '').toLowerCase();