Use configured browser for source windows

This commit is contained in:
2026-08-05 21:15:19 +02:00
parent 6a1568a1dd
commit d90e6c6dd8
2 changed files with 8 additions and 7 deletions
+1
View File
@@ -70,6 +70,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.
- 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.
- 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.
- Keep scraping slow and observable, preserve source URL/status information, and handle blocked pages or missing selectors as explicit errors.
- Supplier data remains a local draft until the user explicitly confirms an Apply / Save action.
+7 -7
View File
@@ -185,7 +185,7 @@ export async function findProductSources(
const candidate = item.candidates?.[0];
if (candidate?.url) {
try {
await openInBrowser(candidate.url);
await openInBrowser(candidate.url, { engine: item.source.browserEngine });
} catch {
// Picture extraction can continue even if the visible browser cannot start.
}
@@ -332,7 +332,7 @@ async function findSourceCandidates(source, product, { includePictures = false }
if (candidates.length) {
let verification = null;
if (includePictures && source.key === "hudy" && product.color && candidates[0].url) {
verification = await verifyHudyVariant(candidates[0].url, product);
verification = await verifyHudyVariant(candidates[0].url, product, source.browserEngine);
candidates[0].verification = verification;
if (verification.matchedUrl) candidates[0].url = verification.matchedUrl;
if (includePictures && verification.pictures?.length) {
@@ -343,7 +343,7 @@ async function findSourceCandidates(source, product, { includePictures = false }
if (includePictures) {
for (const candidate of candidates) {
if (source.key === "hudy" && candidate.url) {
candidate.pictures = await extractPicturesFromPage(candidate.url);
candidate.pictures = await extractPicturesFromPage(candidate.url, source.browserEngine);
} else {
candidate.pictures = extractPictureUrls(html, response.url || attempt.url);
}
@@ -585,7 +585,7 @@ function findColorVariantUrl(html, pageUrl, color) {
return "";
}
async function verifyHudyVariant(url, product) {
async function verifyHudyVariant(url, product, browserEngine = "chromium") {
try {
const eanGroup = Array.isArray(product.eanGroup)
? product.eanGroup
@@ -603,7 +603,7 @@ async function verifyHudyVariant(url, product) {
if (visited.has(page.url)) continue;
visited.add(page.url);
const response = await scrapePage(page.url, { waitAfterLoadMs: 750 });
const response = await scrapePage(page.url, { engine: browserEngine, waitAfterLoadMs: 750 });
const html = response.pageSource;
lastStatus = response.status;
const pageEans = extractPageEans(html);
@@ -705,9 +705,9 @@ function extractPictureUrls(html, pageUrl) {
return urls.slice(0, 12);
}
async function extractPicturesFromPage(url) {
async function extractPicturesFromPage(url, browserEngine = "chromium") {
try {
const response = await scrapePage(url, { waitAfterLoadMs: 750 });
const response = await scrapePage(url, { engine: browserEngine, waitAfterLoadMs: 750 });
return extractHudyGalleryPictureUrls(response.pageSource, response.url || url);
} catch {
return [];