diff --git a/backend/src/tools/koepi/routes.js b/backend/src/tools/koepi/routes.js index 84aa4b8..08c044f 100644 --- a/backend/src/tools/koepi/routes.js +++ b/backend/src/tools/koepi/routes.js @@ -64,6 +64,13 @@ function isExcludedRetailer(retailer) { // Filialen für diesen Händler passt. Ohne erkannten Händler oder ohne gescrapte // Adresse wird NICHT gefiltert (lieber ein Angebot zuviel zeigen als eins zu // Unrecht verstecken, falls marktguru das Layout mal ändert). +// +// STAND JETZT: Die verwendete Such-URL (/search/...?zipCode=...) liefert pro +// Angebot KEINE Adresse, daher ist diese Funktion aktuell praktisch immer +// "true" (kein echter Filter-Effekt). Bleibt drin für den Fall, dass sich das +// Seiten-Layout künftig ändert oder eine andere URL genutzt wird, die +// Adressen liefert (getestet: /bl/{marke}/{ort} tut das, bringt aber einen +// anderen/kleineren Angebots-Pool mit — siehe Git-Historie). function isLocalBranch(retailer, realAddress) { const n = (retailer || '').toLowerCase(); const key = Object.keys(RETAILER_ADDRESSES).find(k => n.includes(k)); @@ -98,11 +105,7 @@ async function scrapeMarktguru(forceRefresh = false) { await page.setViewport({ width:1280, height:800 }); await page.setCookie({ name:'mg_user-settings', value:MG_SETTINGS, domain:'.marktguru.de', path:'/' }); - // Umgestellt von /search/...?zipCode=... auf /bl/{marke}/{ort} — die - // Such-URL zeigt pro Angebot KEINE Adresse an (siehe RAW-Diagnose unten), - // diese Marken+Standort-Seite hingegen schon, was für den Filter auf - // wirklich lokale Filialen nötig ist. - await page.goto('https://www.marktguru.de/bl/koenig-pilsener/duisburg', { +await page.goto('https://www.marktguru.de/search/k%C3%B6nig%20pilsener?zipCode=47259', { waitUntil: 'networkidle2', timeout: 30000, }); // Seite nach unten scrollen damit lazy-loaded Bilder geladen werden @@ -157,19 +160,6 @@ async function scrapeMarktguru(forceRefresh = false) { }); }); - // 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(); @@ -200,13 +190,16 @@ async function scrapeMarktguru(forceRefresh = false) { return hasKP && isTargetRetailer(o.retailer); }); - // Nur Angebote der tatsächlich bekannten, lokalen Filialen behalten (marktguru - // zeigt teils auch weiter entfernte Filialen derselben Kette, z.B. "REWE Dortmund" - // oder einen anderen Netto/Kaufland-Standort — anhand der echten gescrapten - // Adresse rausfiltern statt sie fälschlich mit der lokalen Adresse zu überschreiben) - console.log('🍺 KöPi Adress-Diagnose:', filtered.map(o => - `${o.retailer} | realAddress="${o.realAddress}" | excluded=${isExcludedRetailer(o.retailer)} | local=${isLocalBranch(o.retailer, o.realAddress)}` - ).join('\n ')); + // Nur Angebote der tatsächlich bekannten, lokalen Filialen behalten. Die + // Adress-basierte Prüfung (isLocalBranch) greift nur, wenn marktguru für + // ein Angebot eine echte Adresse liefert — auf der aktuell genutzten + // Such-URL ist das nicht der Fall, daher bleibt sie hier wirkungslos + // (siehe Kommentar an isLocalBranch). Verlässlich funktioniert aktuell nur + // der explizite Namens-Ausschluss (z.B. "REWE Dortmund"). + const excludedNow = filtered.filter(o => isExcludedRetailer(o.retailer)); + if (excludedNow.length) { + console.log('🍺 KöPi: Angebote per Namens-Filter ausgeschlossen:', excludedNow.map(o => o.retailer).join(', ')); + } const localOnly = filtered .filter(o => !isExcludedRetailer(o.retailer))