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)}`) + .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();