mirror of
https://github.com/samsonjs/spirit-tracker.git
synced 2026-04-27 15:07:43 +00:00
fix: Vessel
This commit is contained in:
parent
d98ece6f7f
commit
7ff1bde8bd
1 changed files with 47 additions and 2 deletions
|
|
@ -16,6 +16,27 @@ function normalizeAbsUrl(raw) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Strip noisy Shopify/tracking params so URLs stay stable.
|
||||||
|
// Keep only "variant" since it can represent a distinct product configuration.
|
||||||
|
function normalizeShopifyProductUrl(rawUrl) {
|
||||||
|
try {
|
||||||
|
const u = new URL(String(rawUrl || ""));
|
||||||
|
u.hash = "";
|
||||||
|
|
||||||
|
const keep = new Set(["variant"]);
|
||||||
|
for (const k of [...u.searchParams.keys()]) {
|
||||||
|
if (!keep.has(k)) u.searchParams.delete(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([...u.searchParams.keys()].length === 0) u.search = "";
|
||||||
|
if (u.pathname.length > 1) u.pathname = u.pathname.replace(/\/+$/, "");
|
||||||
|
|
||||||
|
return u.toString();
|
||||||
|
} catch {
|
||||||
|
return String(rawUrl || "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function makeVesselPageUrl(baseUrl, pageNum) {
|
function makeVesselPageUrl(baseUrl, pageNum) {
|
||||||
const u = new URL(normalizeBaseUrl(baseUrl));
|
const u = new URL(normalizeBaseUrl(baseUrl));
|
||||||
u.hash = "";
|
u.hash = "";
|
||||||
|
|
@ -54,6 +75,29 @@ function vesselExtractPrice(block) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Vessel image filenames are often numeric (e.g. 67424.jpg). Grab that.
|
||||||
|
function vesselExtractSkuFromImgOrBlock(imgUrl, block) {
|
||||||
|
// Prefer existing CSPC normalizer if it matches
|
||||||
|
const cspc = normalizeCspc(imgUrl) || "";
|
||||||
|
if (cspc) return cspc;
|
||||||
|
|
||||||
|
// From image URL path
|
||||||
|
try {
|
||||||
|
const u = new URL(String(imgUrl || ""));
|
||||||
|
const m = u.pathname.match(/\/(\d{4,10})\.(?:jpe?g|png|webp)$/i);
|
||||||
|
if (m && m[1]) return m[1];
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
// From raw HTML (src/srcset often contains the numeric filename)
|
||||||
|
const s = String(block || "");
|
||||||
|
const m2 = s.match(/\/cdn\/shop\/products\/(\d{4,10})\.(?:jpe?g|png|webp)/i);
|
||||||
|
if (m2 && m2[1]) return m2[1];
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
function vesselCardToItem(block, base) {
|
function vesselCardToItem(block, base) {
|
||||||
if (!vesselLooksInStock(block)) return null;
|
if (!vesselLooksInStock(block)) return null;
|
||||||
|
|
||||||
|
|
@ -63,6 +107,7 @@ function vesselCardToItem(block, base) {
|
||||||
let url = "";
|
let url = "";
|
||||||
try {
|
try {
|
||||||
url = new URL(decodeHtml(hrefM[1]), base).toString();
|
url = new URL(decodeHtml(hrefM[1]), base).toString();
|
||||||
|
url = normalizeShopifyProductUrl(url);
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -77,8 +122,8 @@ function vesselCardToItem(block, base) {
|
||||||
const img = normalizeAbsUrl(extractFirstImgUrl(block, base));
|
const img = normalizeAbsUrl(extractFirstImgUrl(block, base));
|
||||||
const price = vesselExtractPrice(block);
|
const price = vesselExtractPrice(block);
|
||||||
|
|
||||||
// Try to pull a 6-digit SKU (often their image filenames are CSPC-like).
|
// Prefer numeric filename SKU like 67424.jpg (works for 5-digit too)
|
||||||
const sku = normalizeCspc(img) || "";
|
const sku = vesselExtractSkuFromImgOrBlock(img, block);
|
||||||
|
|
||||||
return { name, price, url, sku, img };
|
return { name, price, url, sku, img };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue