From 90f738ac8eaaf2916029aa6da9b1a98c09a536f6 Mon Sep 17 00:00:00 2001 From: Cedric Date: Thu, 2 Jul 2026 16:04:11 +0200 Subject: [PATCH] Actualiser api.php --- api.php | 151 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 96 insertions(+), 55 deletions(-) diff --git a/api.php b/api.php index 6e86e28..752eba0 100644 --- a/api.php +++ b/api.php @@ -153,26 +153,110 @@ function fetchFromGoUpc($ean) { return $empty; } -// ── NOUVELLE FONCTION : SCRAPPING UPCINDEX.COM (MODIFIÉE AVEC MÉTADONNÉES) ── +// ── FONCTION : SCRAPPING UPCINDEX.COM (CORRIGÉE) ── function fetchFromUpcIndex($ean) { $empty = emptyPhysicalResult(); $url = "https://www.upcindex.com/" . urlencode($ean); $html = httpGet($url, 15); if (!$html) return $empty; - // Recherche du titre - if (preg_match('/]*class="text-center"[^>]*>.*?]*itemprop="name"[^>]*>([^<]+)<\/span>/is', $html, $m)) { - $empty['title'] = trim(strip_tags($m[1])); - } elseif (preg_match('/]*>([^<]+)<\/title>/i', $html, $m)) { - $title = trim($m[1]); - $title = preg_replace('/\s*[-–]\s*UPCindex.*$/i', '', $title); - $empty['title'] = $title; + // 1. Parser le JSON-LD pour le titre français et l'image (plus fiable) + if (preg_match('/]*type="application\/ld\+json"[^>]*>(.*?)<\/script>/is', $html, $jsonMatch)) { + $jsonData = json_decode($jsonMatch[1], true); + if ($jsonData && isset($jsonData['@type']) && $jsonData['@type'] === 'Product') { + // Titre français propre + if (!empty($jsonData['name'])) { + $empty['title'] = trim($jsonData['name']); + } + // Image + if (!empty($jsonData['image'])) { + $empty['poster'] = trim($jsonData['image']); + } + // Brand/éditeur + if (!empty($jsonData['brand']['name'])) { + $empty['publisher'] = trim($jsonData['brand']['name']); + } + } } - // ✅ RÉCUPÉRATION DE L'IMAGE DEPUIS UPCINDEX (première image produit) - // Chercher la première image de produit (après le barcode) - if (preg_match_all('/]*itemprop="http:\/\/schema\.org\/image"[^>]*src="([^"]+)"/i', $html, $matches)) { - // Prendre la première image de produit (pas le barcode) + // 2. Fallback pour le titre : meta twitter:title + if (empty($empty['title']) && preg_match('/]*name="twitter:title"[^>]*content="([^"]+)"/i', $html, $m)) { + $empty['title'] = html_entity_decode(trim($m[1]), ENT_QUOTES | ENT_HTML5, 'UTF-8'); + } + + // 3. Extraire la section product-info pour les métadonnées physiques + if (preg_match('/]*id="product-info"[^>]*itemtype="http:\/\/schema\.org\/ItemList"[^>]*>(.*?)<\/section>/is', $html, $sectionMatch)) { + $productInfo = $sectionMatch[1]; + + // Fonction helper pour extraire une valeur unique depuis dt/dd + $extractValue = function($label) use ($productInfo) { + $pattern = '/]*>' . preg_quote($label, '/') . '<\/dt>\s*]*>([^<]+)<\/dd>/is'; + if (preg_match($pattern, $productInfo, $m)) { + return trim($m[1]); + } + return ''; + }; + + // Directeur + $director = $extractValue('director'); + if (!empty($director)) { + $empty['director'] = $director; + } + + // Acteurs (peut y avoir plusieurs dd pour un seul dt) + if (preg_match('/]*>actor<\/dt>(.*?)(?=]*>([^<]+)<\/dd>/is', $actorSection[1], $actorMatches); + if (!empty($actorMatches[1])) { + $empty['actors'] = implode(', ', array_map('trim', $actorMatches[1])); + } + } + + // Aspect ratio + $aspectRatio = $extractValue('aspect ratio'); + if (!empty($aspectRatio)) { + $empty['aspect_ratio'] = $aspectRatio; + } + + // Nombre de disques + $numDiscs = $extractValue('number of discs'); + if (!empty($numDiscs) && is_numeric($numDiscs)) { + $empty['number_of_discs'] = (int)$numDiscs; + } + + // Format (peut y avoir plusieurs valeurs) + if (preg_match('/]*>format<\/dt>(.*?)(?=]*>([^<]+)<\/dd>/is', $formatSection[1], $formatMatches); + if (!empty($formatMatches[1])) { + $formats = array_map('trim', $formatMatches[1]); + // Chercher un format vidéo pertinent + foreach ($formats as $f) { + if (stripos($f, '4K') !== false || stripos($f, 'UHD') !== false) { + $empty['format'] = '4K Ultra HD'; + break; + } elseif (stripos($f, 'Blu-ray') !== false || stripos($f, 'Bluray') !== false) { + $empty['format'] = 'Blu-ray'; + break; + } elseif (stripos($f, 'DVD') !== false) { + $empty['format'] = 'DVD'; + break; + } + } + // Si pas trouvé, utiliser le premier format + if (empty($empty['format']) && !empty($formats[0])) { + $empty['format'] = $formats[0]; + } + } + } + + // Region code (pour la description) + $regionCode = $extractValue('region code'); + if (!empty($regionCode)) { + $empty['description'] = 'Region ' . $regionCode; + } + } + + // 4. Fallback pour l'image : première image produit (pas le barcode) + if (empty($empty['poster']) && preg_match_all('/]*itemprop="http:\/\/schema\.org\/image"[^>]*src="([^"]+)"/i', $html, $matches)) { foreach ($matches[1] as $imgSrc) { if (strpos($imgSrc, 'barcode.png') === false && strpos($imgSrc, 'upcindex.com') !== false) { $empty['poster'] = 'https:' . $imgSrc; @@ -181,55 +265,12 @@ function fetchFromUpcIndex($ean) { } } - // ✅ RÉCUPÉRATION DES MÉTADONNÉES PHYSIQUES - // Directeur - if (preg_match('/]*>director<\/dt>\s*]*>([^<]+)<\/dd>/is', $html, $m)) { - $empty['director'] = trim($m[1]); - } - - // Acteurs - if (preg_match_all('/]*>actor<\/dt>\s*]*>([^<]+)<\/dd>/is', $html, $actorsMatches)) { - $empty['actors'] = implode(', ', array_map('trim', $actorsMatches[1])); - } - - // Format - if (preg_match('/]*>format<\/dt>\s*]*>([^<]+)<\/dd>/is', $html, $m)) { - $format = trim($m[1]); - if (stripos($format, 'DVD') !== false) $empty['format'] = 'DVD'; - elseif (stripos($format, 'Blu-ray') !== false) $empty['format'] = 'Blu-ray'; - elseif (stripos($format, '4K') !== false) $empty['format'] = '4K Ultra HD'; - } - - // Aspect ratio - if (preg_match('/]*>aspect ratio<\/dt>\s*]*>([^<]+)<\/dd>/is', $html, $m)) { - $empty['aspect_ratio'] = trim($m[1]); - } - - // Nombre de disques - if (preg_match('/]*>number of discs<\/dt>\s*]*>(\d+)<\/dd>/is', $html, $m)) { - $empty['number_of_discs'] = (int)$m[1]; - } - - // Brand/Publisher - if (preg_match('/]*>brand<\/dt>\s*]*>([^<]+)<\/dd>/is', $html, $m)) { - $empty['publisher'] = trim($m[1]); - } - - // Region code - if (preg_match('/]*>region code<\/dt>\s*]*>([^<]+)<\/dd>/is', $html, $m)) { - $empty['description'] = 'Region ' . trim($m[1]); - } - // Nettoyage du titre if (!empty($empty['title'])) { $empty['title'] = html_entity_decode($empty['title'], ENT_QUOTES | ENT_HTML5, 'UTF-8'); $empty['title'] = trim($empty['title']); } - if (!empty($empty['title'])) { - $empty['format'] = detectFormat($empty['title']); - } - return $empty; }