Actualiser api.php

This commit is contained in:
2026-06-25 11:57:19 +02:00
parent 37c5fa1b48
commit cb148b4c58
+77 -54
View File
@@ -115,7 +115,7 @@ function extractYear($dateStr) {
return ''; return '';
} }
// ── DVDcover.com (scraping précis) ── // ── DVDcover.com (avec validation du film) ──
function fetchDVDCover($title, $year = '', $format = 'bluray') { function fetchDVDCover($title, $year = '', $format = 'bluray') {
if (empty($title)) return null; if (empty($title)) return null;
@@ -133,12 +133,12 @@ function fetchDVDCover($title, $year = '', $format = 'bluray') {
$dcFormat = $formatMap[strtolower($format)] ?? 'blu-ray'; $dcFormat = $formatMap[strtolower($format)] ?? 'blu-ray';
// URL de recherche DVDcover // Recherche plus spécifique avec titre + année
$searchUrl = "https://www.dvdcover.com/?s=" . urlencode($cleanTitle); $searchUrl = "https://www.dvdcover.com/?s=" . urlencode($cleanTitle . " " . $year);
$html = httpGet($searchUrl, 8, $ua); $html = httpGet($searchUrl, 8, $ua);
if (!$html) { if (!$html) {
error_log("DVDCover: Échec recherche pour '$title'"); error_log("DVDCover: Échec recherche pour '$title $year'");
return null; return null;
} }
@@ -148,87 +148,110 @@ function fetchDVDCover($title, $year = '', $format = 'bluray') {
'format' => $format, 'format' => $format,
]; ];
// DVDcover utilise WordPress - les articles ont la classe "post" // Chercher tous les articles de covers
// Chercher les liens vers les pages individuelles de covers preg_match_all('/<article[^>]*id=["\']post-\d+["\'][^>]*>(.*?)<\/article>/is', $html, $articles);
preg_match_all('/<article[^>]*class=["\'][^"\']*post[^"\']*["\'][^>]*>.*?<a[^>]+href=["\']([^"\']+)["\'][^>]*>.*?<\/article>/is', $html, $articles);
if (!empty($articles[1])) { if (!empty($articles[1])) {
// Parcourir les résultats $bestMatch = null;
foreach ($articles[1] as $coverPage) { $bestScore = 0;
foreach ($articles[1] as $article) {
// Extraire le lien vers la page du cover
if (!preg_match('/<a[^>]+href=["\']([^"\']+)["\'][^>]*>/i', $article, $linkMatch)) {
continue;
}
$coverPage = $linkMatch[1];
if (strpos($coverPage, 'http') !== 0) { if (strpos($coverPage, 'http') !== 0) {
$coverPage = 'https://www.dvdcover.com' . $coverPage; $coverPage = 'https://www.dvdcover.com' . $coverPage;
} }
// Extraire le titre du cover depuis l'article
$articleTitle = '';
if (preg_match('/<h2[^>]*class=["\'][^"\']*entry-title[^"\']*["\'][^>]*>([^<]+)<\/h2>/i', $article, $titleMatch)) {
$articleTitle = trim(strip_tags($titleMatch[1]));
}
// Calculer un score de correspondance
$score = 0;
$articleTitleLower = strtolower($articleTitle);
$searchTitleLower = strtolower($cleanTitle);
// Le titre contient-il le film recherché ?
if (strpos($articleTitleLower, $searchTitleLower) !== false) {
$score += 50;
}
// L'année correspond-elle ?
if (!empty($year) && strpos($articleTitle, $year) !== false) {
$score += 30;
}
// Le format correspond-il ?
if (stripos($articleTitle, $format) !== false ||
stripos($articleTitle, $dcFormat) !== false) {
$score += 20;
}
// Si le score est trop bas, on ignore ce résultat
if ($score < 30) {
continue;
}
// Récupérer la page du cover
$coverHtml = httpGet($coverPage, 8, $ua); $coverHtml = httpGet($coverPage, 8, $ua);
if (!$coverHtml) continue; if (!$coverHtml) continue;
// Méthode 1 : Chercher l'image principale dans le contenu de l'article // Chercher l'image principale
// DVDcover met les jaquettes dans <figure> ou <div class="entry-content"> $poster = '';
if (preg_match('/<figure[^>]*>.*?<img[^>]+src=["\']([^"\']+)["\'][^>]*>/is', $coverHtml, $m)) {
$img = $m[1]; // Méthode 1 : Image dans le contenu principal
// Vérifier que c'est bien une jaquette (pas une image de thème) if (preg_match('/<div[^>]*class=["\'][^"\']*entry-content[^"\']*["\'][^>]*>.*?<img[^>]+src=["\']([^"\']+\/wp-content\/uploads\/[^"\']+\.(?:jpg|jpeg|webp))["\'][^>]*>/is', $coverHtml, $imgMatch)) {
if (strpos($img, '/wp-content/uploads/') !== false && $poster = $imgMatch[1];
strpos($img, '/wp-content/themes/') === false &&
(strpos($img, '.jpg') !== false || strpos($img, '.jpeg') !== false || strpos($img, '.webp') !== false)) {
$result['poster'] = $img;
}
} }
// Méthode 2 : Chercher dans entry-content // Méthode 2 : Image dans figure
if (empty($result['poster']) && preg_match('/<div[^>]*class=["\'][^"\']*entry-content[^"\']*["\'][^>]*>.*?<img[^>]+src=["\']([^"\']+)["\'][^>]*>/is', $coverHtml, $m)) { if (empty($poster) && preg_match('/<figure[^>]*>.*?<img[^>]+src=["\']([^"\']+\/wp-content\/uploads\/[^"\']+\.(?:jpg|jpeg|webp))["\'][^>]*>/is', $coverHtml, $imgMatch)) {
$img = $m[1]; $poster = $imgMatch[1];
if (strpos($img, '/wp-content/uploads/') !== false &&
strpos($img, '/wp-content/themes/') === false) {
$result['poster'] = $img;
}
} }
// Méthode 3 : Chercher toutes les images et prendre la plus grande // Méthode 3 : Première image valide
if (empty($result['poster'])) { if (empty($poster)) {
preg_match_all('/<img[^>]+src=["\']([^"\']+\/wp-content\/uploads\/[^"\']+\.(?:jpg|jpeg|webp))["\'][^>]*>/i', $coverHtml, $allImages); preg_match_all('/<img[^>]+src=["\']([^"\']+\/wp-content\/uploads\/[^"\']+\.(?:jpg|jpeg|webp))["\'][^>]*>/i', $coverHtml, $allImages);
if (!empty($allImages[1])) { if (!empty($allImages[1])) {
// Prendre la première image qui n'est pas un logo ou icône
foreach ($allImages[1] as $img) { foreach ($allImages[1] as $img) {
if (strpos($img, 'logo') === false && if (strpos($img, 'logo') === false &&
strpos($img, 'icon') === false && strpos($img, 'icon') === false &&
strpos($img, 'banner') === false && strpos($img, 'banner') === false &&
strpos($img, 'bg') === false && strpos($img, 'bg') === false &&
strpos($img, 'button') === false) { strpos($img, 'button') === false &&
$result['poster'] = $img; strpos($img, '300x200') === false && // Éviter les miniatures
strpos($img, '150x150') === false) {
$poster = $img;
break; break;
} }
} }
} }
} }
// Extraire le titre // Si on a une image et un bon score, on la garde
if (preg_match('/<h1[^>]*class=["\'][^"\']*entry-title[^"\']*["\'][^>]*>([^<]+)<\/h1>/i', $coverHtml, $titleMatch)) { if (!empty($poster) && $score > $bestScore) {
$result['title'] = trim(strip_tags($titleMatch[1])); $bestScore = $score;
} elseif (preg_match('/<title[^>]*>([^<]+)<\/title>/i', $coverHtml, $titleMatch)) { $bestMatch = [
$result['title'] = trim(strip_tags($titleMatch[1])); 'poster' => $poster,
} 'title' => $articleTitle,
];
// Si on a trouvé une image, on arrête // Si score parfait, on arrête tout de suite
if (!empty($result['poster'])) { if ($score >= 100) {
break;
}
}
}
// Fallback : chercher directement dans la page de résultats
if (empty($result['poster'])) {
preg_match_all('/<img[^>]+src=["\']([^"\']+\/wp-content\/uploads\/[^"\']+\.(?:jpg|jpeg|webp))["\'][^>]*>/i', $html, $allImages);
if (!empty($allImages[1])) {
foreach ($allImages[1] as $img) {
if (strpos($img, 'logo') === false &&
strpos($img, 'icon') === false &&
strpos($img, 'banner') === false &&
strpos($img, 'bg') === false) {
$result['poster'] = $img;
break; break;
} }
} }
} }
if ($bestMatch) {
$result = $bestMatch;
}
} }
return (!empty($result['poster'])) ? $result : null; return (!empty($result['poster'])) ? $result : null;