Run source lookup headless and reject Idealo thumbnails

This commit is contained in:
2026-08-06 00:39:50 +02:00
parent d3d1147a3a
commit 6f2d998754
3 changed files with 17 additions and 9 deletions
+2 -1
View File
@@ -73,6 +73,7 @@ This project replaces the Excel/VBA workflow named `Catalog maker - 20` with a N
- Do not implement new scraping with raw `fetch`, regex-only HTML parsing, Selenium or direct HTTP shortcuts. - Do not implement new scraping with raw `fetch`, regex-only HTML parsing, Selenium or direct HTTP shortcuts.
- Scrapers must use controlled browser navigation, selectors, explicit waits and bounded request counts. - Scrapers must use controlled browser navigation, selectors, explicit waits and bounded request counts.
- The configured browser engine for a source is authoritative. If a source says `firefox`, launch Firefox or fail loudly; do not silently fall back to Chromium, Edge or another browser. - The configured browser engine for a source is authoritative. If a source says `firefox`, launch Firefox or fail loudly; do not silently fall back to Chromium, Edge or another browser.
- Automated source lookup, mapping checks and picture lookup must run headless/in the background by default. Open a visible browser only for explicit user `Open` actions or deliberate diagnostics after an error.
- Visible source windows, URL health checks, source lookup and picture parsing must all use the same configured browser engine from that source's database setting. - Visible source windows, URL health checks, source lookup and picture parsing must all use the same configured browser engine from that source's database setting.
- Source candidate `Open` actions in the UI must call the backend source opener with `manufacturerId`, `sourceKey` and URL. Do not use plain `target="_blank"` source links for mapped supplier/manufacturer sources because that ignores the configured browser engine. - Source candidate `Open` actions in the UI must call the backend source opener with `manufacturerId`, `sourceKey` and URL. Do not use plain `target="_blank"` source links for mapped supplier/manufacturer sources because that ignores the configured browser engine.
- Keep scraping slow and observable, preserve source URL/status information, and handle blocked pages or missing selectors as explicit errors. - Keep scraping slow and observable, preserve source URL/status information, and handle blocked pages or missing selectors as explicit errors.
@@ -193,7 +194,7 @@ There are three selectable data sources:
- Review UI: show picture size, source, target assignment, duplicate state, per-row save and batch save actions. - Review UI: show picture size, source, target assignment, duplicate state, per-row save and batch save actions.
- Hudy picture parsing uses the correct product color variant, checks EANs and extracts large gallery images. - Hudy picture parsing uses the correct product color variant, checks EANs and extracts large gallery images.
- Idealo uses the browser adapter and is intended mainly as a picture source. - Idealo uses the browser adapter and is intended mainly as a picture source.
- Idealo picture parsing must read product gallery images from Splide gallery markup (`splide__track`, `splide__list`, `splide__slide`) and choose the largest available URL from `srcset`, `data-srcset`, `data-large`, `data-original`, `data-src` or `src`. Do not use search-result thumbnails or small preview URLs as production picture candidates when gallery images exist. - Idealo picture parsing must read product gallery images from Splide gallery markup (`splide__track`, `splide__list`, `splide__slide`) and choose the largest available URL from `srcset`, `data-srcset`, `data-large`, `data-original`, `data-src` or `src`. Do not use search-result thumbnails or small preview URLs as production picture candidates. If no Idealo gallery is found, return no Idealo pictures and show the quality/missing warning instead of saving thumbnails.
- Image preview is square. - Image preview is square.
- Settings is at the bottom of the left panel; database status is directly above it. - Settings is at the bottom of the left panel; database status is directly above it.
+3 -8
View File
@@ -299,7 +299,7 @@ async function findSourceCandidates(source, product, { includePictures = false }
const result = await searchInBrowser({ const result = await searchInBrowser({
url: attempt.url, url: attempt.url,
engine: source.browserEngine, engine: source.browserEngine,
headless: source.browserHeadless, headless: true,
waitAfterLoadMs: source.waitAfterLoadMs, waitAfterLoadMs: source.waitAfterLoadMs,
}); });
@@ -333,12 +333,6 @@ async function findSourceCandidates(source, product, { includePictures = false }
candidates: buildManualSearchCandidates(searchAttempts, product), candidates: buildManualSearchCandidates(searchAttempts, product),
}; };
} catch (error) { } catch (error) {
try {
await openInBrowser(attempt.url, { engine: source.browserEngine });
} catch {
// The manual candidate below remains available even if the browser cannot start.
}
return { return {
source, source,
query: attempt.query, query: attempt.query,
@@ -355,6 +349,7 @@ async function findSourceCandidates(source, product, { includePictures = false }
try { try {
const response = await scrapePage(attempt.url, { const response = await scrapePage(attempt.url, {
engine: source.browserEngine, engine: source.browserEngine,
headless: true,
waitAfterLoadMs: source.waitAfterLoadMs, waitAfterLoadMs: source.waitAfterLoadMs,
}); });
const html = response.pageSource; const html = response.pageSource;
@@ -768,7 +763,7 @@ export function extractIdealoGalleryPictureUrls(html, pageUrl) {
if (best) return [best]; if (best) return [best];
} }
return extractPictureUrls(source, pageUrl); return [];
} }
function pickBestImageUrlFromMarkup(markup, pageUrl) { function pickBestImageUrlFromMarkup(markup, pageUrl) {
+12
View File
@@ -31,3 +31,15 @@ test("idealo gallery parser prefers large splide images over thumbnails", () =>
]); ]);
}); });
test("idealo gallery parser does not fall back to search thumbnails", () => {
const html = `
<main>
<article class="search-result">
<img src="//img.idealo.com/folder/Product/200123/4/200123456/result_thumb_150x150.jpg">
</article>
</main>`;
const urls = extractIdealoGalleryPictureUrls(html, "https://www.idealo.de/preisvergleich/MainSearchProductCategory.html?q=123");
assert.deepEqual(urls, []);
});