From 055a7636cce65cc43642fd4abe37933199873998 Mon Sep 17 00:00:00 2001 From: Cedric Date: Wed, 24 Jun 2026 14:16:55 +0200 Subject: [PATCH] Actualiser api.php --- api.php | 202 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 109 insertions(+), 93 deletions(-) diff --git a/api.php b/api.php index bcaa362..55cbc2e 100644 --- a/api.php +++ b/api.php @@ -105,17 +105,18 @@ function extractYear($dateStr) { return ''; } +// ── API DVDFr (NOUVELLE APPROCHE : Scraping HTML car l'API XML est cassée) ── function fetchDVDFr($ean, $pdo) { - if (empty($ean) || strlen($ean) < 8) { - error_log("DVDFr: EAN invalide ou vide - '$ean'"); - return null; - } + if (empty($ean) || strlen($ean) < 8) return null; - $ua = 'MonCinema/1.0 (collection privée; contact@moncineapp.fr)'; + $cacheKey = 'dvdfr_new_' . md5($ean); + $cached = getCache($pdo, $cacheKey); + if ($cached) return $cached; - // Étape 1 : recherche par gencode - $searchUrl = "https://www.dvdfr.com/api/search.php?gencode=" . urlencode($ean); - error_log("DVDFr: Appel API search - URL: $searchUrl"); + $ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'; + + // Étape 1 : Recherche via le site DVDfr (page HTML) + $searchUrl = "https://www.dvdfr.com/search/?q=" . urlencode($ean); $ch = curl_init($searchUrl); curl_setopt_array($ch, [ @@ -125,53 +126,53 @@ function fetchDVDFr($ean, $pdo) { CURLOPT_SSL_VERIFYPEER => false, CURLOPT_USERAGENT => $ua, CURLOPT_FOLLOWLOCATION => true, - CURLOPT_HTTPHEADER => ['Accept: application/xml, text/xml, */*'], + CURLOPT_HTTPHEADER => [ + 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7', + ], ]); - $res = curl_exec($ch); + $html = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); - if (!$res) { - error_log("DVDFr: Échec de la requête search - HTTP $httpCode"); + if (!$html || $httpCode !== 200) { + error_log("DVDFr: Échec recherche HTML - HTTP $httpCode"); return null; } - error_log("DVDFr: Réponse search reçue - " . substr($res, 0, 200)); + // Étape 2 : Extraire le lien vers la fiche du film depuis les résultats de recherche + $dvdUrl = null; - libxml_use_internal_errors(true); - $xml = simplexml_load_string($res); - $xmlErrors = libxml_get_errors(); - libxml_clear_errors(); + // Chercher le premier résultat qui correspond à l'EAN + if (preg_match('/]+href=["\']([^"\']+\.html)["\'][^>]*class=["\'][^"\']*result[^"\']*["\'][^>]*>/i', $html, $matches)) { + $dvdUrl = $matches[1]; + if (strpos($dvdUrl, 'http') !== 0) { + $dvdUrl = 'https://www.dvdfr.com' . $dvdUrl; + } + } - if (!$xml) { - error_log("DVDFr: Impossible de parser le XML search - Erreurs: " . json_encode($xmlErrors)); + // Méthode alternative : chercher directement l'EAN dans le HTML + if (!$dvdUrl && preg_match('/href=["\']([^"\']*' . preg_quote($ean, '/') . '[^"\']*\.html)["\']/i', $html, $matches)) { + $dvdUrl = $matches[1]; + if (strpos($dvdUrl, 'http') !== 0) { + $dvdUrl = 'https://www.dvdfr.com' . $dvdUrl; + } + } + + // Méthode 3 : chercher n'importe quel lien vers une fiche DVD/Blu-ray + if (!$dvdUrl && preg_match('/]+href=["\'](https:\/\/www\.dvdfr\.com\/(?:dvd|blu-ray)\/[^"\']+\.html)["\']/i', $html, $matches)) { + $dvdUrl = $matches[1]; + } + + if (!$dvdUrl) { + error_log("DVDFr: Aucune fiche trouvée pour EAN $ean"); return null; } - // 🔥 Meilleure détection de la structure XML - $dvdId = null; + error_log("DVDFr: Fiche trouvée - $dvdUrl"); - if (isset($xml->dvd) && count($xml->dvd) > 0) { - $dvdId = (string)$xml->dvd[0]->id; - } elseif (isset($xml->resultats) && isset($xml->resultats->dvd)) { - $dvdId = (string)$xml->resultats->dvd[0]->id; - } elseif (isset($xml->results) && count($xml->results) > 0) { - $dvdId = (string)$xml->results[0]->id; - } - - if (empty($dvdId)) { - error_log("DVDFr: Aucun ID DVD trouvé dans la réponse search"); - error_log("DVDFr: Structure XML: " . json_encode($xml)); - return null; - } - - error_log("DVDFr: ID DVD trouvé - $dvdId"); - - // Étape 2 : fiche complète - $ficheUrl = "https://www.dvdfr.com/api/dvd.php?id=" . urlencode($dvdId); - error_log("DVDFr: Appel API fiche - URL: $ficheUrl"); - - $ch2 = curl_init($ficheUrl); + // Étape 3 : Récupérer la fiche complète + $ch2 = curl_init($dvdUrl); curl_setopt_array($ch2, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 8, @@ -179,66 +180,81 @@ function fetchDVDFr($ean, $pdo) { CURLOPT_SSL_VERIFYPEER => false, CURLOPT_USERAGENT => $ua, CURLOPT_FOLLOWLOCATION => true, - CURLOPT_HTTPHEADER => ['Accept: application/xml, text/xml, */*'], + CURLOPT_HTTPHEADER => [ + 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'Accept-Language: fr-FR,fr;q=0.9', + ], ]); - $res2 = curl_exec($ch2); - $httpCode2 = curl_getinfo($ch2, CURLINFO_HTTP_CODE); + $ficheHtml = curl_exec($ch2); curl_close($ch2); - if (!$res2) { - error_log("DVDFr: Échec de la requête fiche - HTTP $httpCode2"); + if (!$ficheHtml) { + error_log("DVDFr: Impossible de charger la fiche"); return null; } - error_log("DVDFr: Réponse fiche reçue - " . substr($res2, 0, 300)); - - libxml_use_internal_errors(true); - $fiche = simplexml_load_string($res2); - $ficheErrors = libxml_get_errors(); - libxml_clear_errors(); - - if (!$fiche) { - error_log("DVDFr: Impossible de parser le XML fiche - Erreurs: " . json_encode($ficheErrors)); - return null; - } - - // 🔥 Meilleure détection de la fiche DVD - $dvd = null; - - if (isset($fiche->dvd) && count($fiche->dvd) > 0) { - $dvd = $fiche->dvd[0]; - } elseif (isset($fiche->fiche)) { - $dvd = $fiche->fiche; - } elseif (isset($fiche->product)) { - $dvd = $fiche->product; - } - - if (!$dvd) { - error_log("DVDFr: Structure de fiche non reconnue"); - error_log("DVDFr: Structure XML fiche: " . json_encode($fiche)); - return null; - } - - // Extraction des données avec fallbacks - $poster = ''; - if (isset($dvd->cover)) { - $poster = (string)$dvd->cover; - } elseif (isset($dvd->covers) && isset($dvd->covers->cover)) { - $poster = (string)$dvd->covers->cover[0]; - } elseif (isset($dvd->image)) { - $poster = (string)$dvd->image; - } - + // Étape 4 : Extraire les données depuis le HTML de la fiche $result = [ - 'poster' => $poster, - 'publisher' => isset($dvd->editeur) ? (string)$dvd->editeur : '', - 'format' => isset($dvd->type) ? (string)$dvd->type : '', - 'length' => isset($dvd->duree) ? (string)$dvd->duree : '', - 'aspect' => isset($dvd->formatimage) ? (string)$dvd->formatimage : '', - 'discs' => isset($dvd->nbdisques) ? (string)$dvd->nbdisques : '', + 'poster' => '', + 'publisher' => '', + 'format' => '', + 'length' => '', + 'aspect' => '', + 'discs' => '', ]; - error_log("DVDFr: Données extraites - " . json_encode($result)); + // Extraction de l'affiche (jaquette) + if (preg_match('/]+class=["\'][^"\']*cover[^"\']*["\'][^>]+src=["\']([^"\']+)["\']/i', $ficheHtml, $matches)) { + $result['poster'] = $matches[1]; + } elseif (preg_match('/]+alt=["\'][^"\']*(?:jaquette|cover|pochette)[^"\']*["\'][^>]+src=["\']([^"\']+)["\']/i', $ficheHtml, $matches)) { + $result['poster'] = $matches[1]; + } elseif (preg_match('/src=["\']([^"\']+(?:cover|jaquette|pochette)[^"\']*\.(?:jpg|png|webp))["\']/i', $ficheHtml, $matches)) { + $result['poster'] = $matches[1]; + } + + // Extraction de l'éditeur + if (preg_match('/(?:éditeur|distributeur|studio)\s*[:<\/]>\s*([^<]+)/i', $ficheHtml, $matches)) { + $result['publisher'] = trim(strip_tags($matches[1])); + } + + // Extraction du format (Blu-ray, DVD, 4K, etc.) + if (preg_match('/(4k\s*ultra\s*hd|ultra\s*hd|blu[\s-]?ray|dvd|coffret)/i', $ficheHtml, $matches)) { + $format = strtoupper(trim($matches[1])); + if (strpos($format, '4K') !== false || strpos($format, 'ULTRA') !== false) { + $result['format'] = '4K Ultra HD'; + } elseif (strpos($format, 'BLU') !== false) { + $result['format'] = 'Blu-ray'; + } elseif (strpos($format, 'DVD') !== false) { + $result['format'] = 'DVD'; + } elseif (strpos($format, 'COFFRET') !== false) { + $result['format'] = 'Coffret'; + } + } + + // Extraction de la durée + if (preg_match('/(?:durée|duree|duration)\s*[:<\/]>\s*(\d+)\s*(?:min|mn|h)/i', $ficheHtml, $matches)) { + $result['length'] = trim($matches[1]) . ' min'; + } + + // Extraction de l'aspect ratio + if (preg_match('/(?:format\s*image|aspect\s*ratio|ratio)\s*[:<\/]>\s*([0-9.]+\s*[:\.]\s*[0-9.]+)/i', $ficheHtml, $matches)) { + $result['aspect'] = trim($matches[1]); + } + + // Extraction du nombre de disques + if (preg_match('/(?:nombre\s*de\s*disques?|disques?|nb\s*disques?)\s*[:<\/]>\s*(\d+)/i', $ficheHtml, $matches)) { + $result['discs'] = trim($matches[1]); + } + + // Nettoyage des données + $result = array_map(function($val) { + return trim(strip_tags(html_entity_decode($val, ENT_QUOTES | ENT_HTML5, 'UTF-8'))); + }, $result); + + // Mise en cache si on a au moins une donnée + if (!empty($result['poster']) || !empty($result['publisher'])) { + setCache($pdo, $cacheKey, $result, 'dvdfr'); + } return (!empty($result['poster']) || !empty($result['publisher'])) ? $result : null; }