Version stable : Synthèse 3 cinémas avec affiches et horaires

This commit is contained in:
2026-02-19 14:06:46 +01:00
commit 7fb82310e7
15 changed files with 1013 additions and 0 deletions
+106
View File
@@ -0,0 +1,106 @@
import os, json, logging, requests, re, time
from datetime import datetime
from flask import Flask, render_template, redirect, url_for
from bs4 import BeautifulSoup
app = Flask(__name__)
# Logs en mode "Info" pour voir le suivi dans le terminal
logging.basicConfig(level=logging.INFO, format='%(message)s')
logger = logging.getLogger("Cratere_Scraper")
CACHE_FILE = "/data/movies_cache.json"
HEADERS = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36'}
def get_cratere_date():
"""Génère le format 'Jeu. 19/02' correspondant au site"""
jours_courts = ["Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim"]
now = datetime.now()
day_short = jours_courts[now.weekday()]
return f"{day_short}. {now.day:02d}/{now.month:02d}"
def scrape_cratere_only():
url_main = "https://www.cinemalecratere.fr/films"
target_date = get_cratere_date()
logger.info(f"\n[DEBUG] --- DÉBUT SCRAPING LE CRATÈRE ---")
logger.info(f"[DEBUG] Date cible : {target_date}")
movies_today = []
session = requests.Session()
try:
r = session.get(url_main, headers=HEADERS, timeout=15)
soup = BeautifulSoup(r.content, 'html.parser')
# On cherche les div avec l'attribut data-search (vu sur ta capture)
items = soup.find_all('div', attrs={'data-search': True})
logger.info(f"[DEBUG] {len(items)} blocs trouvés sur la page principale.")
# Dictionnaire pour éviter de scraper deux fois le même film s'il y a 2 séances
seen_movies = {}
for item in items:
data_search = item['data-search']
if target_date in data_search:
# 1. Extraction Titre
title_tag = item.find('span', class_='uk-text-bold')
title = title_tag.get_text(strip=True) if title_tag else "Titre inconnu"
# 2. Extraction Heure (ex: 16h00)
time_match = re.search(r'(\d{2}h\d{2})', data_search)
show_time = time_match.group(0).replace('h', ':') if time_match else "Séance"
if title not in seen_movies:
# 3. On suit le lien pour l'affiche
img_url = ""
link_tag = item.find('a', href=True)
if link_tag:
detail_url = "https://www.cinemalecratere.fr" + link_tag['href']
logger.info(f"[DEBUG] -> Visite page détail : {title}")
try:
r_detail = session.get(detail_url, headers=HEADERS, timeout=10)
soup_detail = BeautifulSoup(r_detail.content, 'html.parser')
# Sélecteur précis : img avec la classe el-image (vu sur ta capture)
img_tag = soup_detail.find('img', class_='el-image')
if img_tag:
img_url = img_tag.get('src')
# Gérer les chemins relatifs
if img_url and not img_url.startswith('http'):
img_url = "https://www.cinemalecratere.fr" + img_url
except Exception as e:
logger.error(f"[DEBUG] Erreur page détail {title}: {e}")
seen_movies[title] = {
"title": title,
"img": img_url,
"times": [show_time],
"cinema": "Le Cratère"
}
# Petit délai pour ne pas brusquer le serveur
time.sleep(0.3)
else:
# Si on a déjà vu le film (autre séance), on ajoute juste l'heure
if show_time not in seen_movies[title]["times"]:
seen_movies[title]["times"].append(show_time)
movies_today = list(seen_movies.values())
except Exception as e:
logger.error(f"[DEBUG] Erreur critique : {e}")
logger.info(f"[DEBUG] FIN : {len(movies_today)} films trouvés pour aujourd'hui.")
return movies_today
@app.route('/')
def index():
# Force le rafraîchissement au chargement pour tester
films = scrape_cratere_only()
# Tri par heure de la première séance
films = sorted(films, key=lambda x: x['times'][0])
return render_template('index.html', films=films)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)