mirror of
https://github.com/clucraft/PriceGhost.git
synced 2026-06-29 15:59:39 +02:00
Extract stock status from JSON-LD availability field
Now extracts availability/stock status from JSON-LD structured data (e.g., "https://schema.org/OutOfStock"). This fixes stock detection for sites like Ubiquiti Store that provide availability in JSON-LD. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
f188ad4ff1
commit
a8a2562cee
1 changed files with 18 additions and 3 deletions
|
|
@ -729,12 +729,15 @@ export async function scrapeProduct(url: string): Promise<ScrapedProduct> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try JSON-LD structured data
|
// Try JSON-LD structured data
|
||||||
if (!result.price || !result.name) {
|
if (!result.price || !result.name || result.stockStatus === 'unknown') {
|
||||||
const jsonLdData = extractJsonLd($);
|
const jsonLdData = extractJsonLd($);
|
||||||
if (jsonLdData) {
|
if (jsonLdData) {
|
||||||
if (!result.name && jsonLdData.name) result.name = jsonLdData.name;
|
if (!result.name && jsonLdData.name) result.name = jsonLdData.name;
|
||||||
if (!result.price && jsonLdData.price) result.price = jsonLdData.price;
|
if (!result.price && jsonLdData.price) result.price = jsonLdData.price;
|
||||||
if (!result.imageUrl && jsonLdData.image) result.imageUrl = jsonLdData.image;
|
if (!result.imageUrl && jsonLdData.image) result.imageUrl = jsonLdData.image;
|
||||||
|
if (result.stockStatus === 'unknown' && jsonLdData.stockStatus) {
|
||||||
|
result.stockStatus = jsonLdData.stockStatus;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -789,11 +792,12 @@ interface JsonLdOffer {
|
||||||
priceCurrency?: string;
|
priceCurrency?: string;
|
||||||
lowPrice?: string | number;
|
lowPrice?: string | number;
|
||||||
priceSpecification?: JsonLdPriceSpecification;
|
priceSpecification?: JsonLdPriceSpecification;
|
||||||
|
availability?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractJsonLd(
|
function extractJsonLd(
|
||||||
$: CheerioAPI
|
$: CheerioAPI
|
||||||
): { name?: string; price?: ParsedPrice; image?: string } | null {
|
): { name?: string; price?: ParsedPrice; image?: string; stockStatus?: StockStatus } | null {
|
||||||
try {
|
try {
|
||||||
const scripts = $('script[type="application/ld+json"]');
|
const scripts = $('script[type="application/ld+json"]');
|
||||||
for (let i = 0; i < scripts.length; i++) {
|
for (let i = 0; i < scripts.length; i++) {
|
||||||
|
|
@ -804,7 +808,7 @@ function extractJsonLd(
|
||||||
const product = findProduct(data);
|
const product = findProduct(data);
|
||||||
|
|
||||||
if (product) {
|
if (product) {
|
||||||
const result: { name?: string; price?: ParsedPrice; image?: string } = {};
|
const result: { name?: string; price?: ParsedPrice; image?: string; stockStatus?: StockStatus } = {};
|
||||||
|
|
||||||
if (product.name) {
|
if (product.name) {
|
||||||
result.name = product.name;
|
result.name = product.name;
|
||||||
|
|
@ -828,6 +832,17 @@ function extractJsonLd(
|
||||||
currency,
|
currency,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extract stock status from availability
|
||||||
|
if (offer.availability) {
|
||||||
|
const avail = offer.availability.toLowerCase();
|
||||||
|
if (avail.includes('instock') || avail.includes('in_stock')) {
|
||||||
|
result.stockStatus = 'in_stock';
|
||||||
|
} else if (avail.includes('outofstock') || avail.includes('out_of_stock') ||
|
||||||
|
avail.includes('soldout') || avail.includes('sold_out')) {
|
||||||
|
result.stockStatus = 'out_of_stock';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (product.image) {
|
if (product.image) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue