🎯 Major achievements: - Scraped 133,358 courses from 2010-2026 (17 years) - Extracted 1,753,172 athlete results - Fixed season calculation bug for December months - Implemented ultra-fast scraping without Selenium (100x faster) 📊 Data coverage: - Temporal: 2010-2026 (complete) - Monthly: All 12 months covered - Geographic: 20,444 unique locations - Results: 190.9 results per course average 🚀 Technical improvements: - Season calculation corrected for FFA calendar system - Sequential scraping for stability (no driver conflicts) - Complete results extraction with all athlete data - Club search functionality (found Haute Saintonge Athlétisme) 📁 New scripts: - scrape_fast.py: Ultra-fast period scraping (requests + bs4) - extract_results_complete.py: Complete results extraction - combine_all_periods.py: Data consolidation tool ⏱️ Performance: - Scraping: 16.1 minutes for 1,241 periods - Extraction: 3 hours for 9,184 courses with results - Total: 1,886,530 records extracted
98 lines
3.0 KiB
Python
98 lines
3.0 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Script pour combiner toutes les périodes scrapées en un seul fichier
|
|
Et préparer les données pour l'extraction des résultats
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import glob
|
|
import logging
|
|
import pandas as pd
|
|
from tqdm import tqdm
|
|
|
|
def combine_periods():
|
|
"""Combiner tous les fichiers de périodes en un seul CSV"""
|
|
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format='%(asctime)s - %(levelname)s - %(message)s'
|
|
)
|
|
|
|
logging.info("=== COMBINAISON DES PÉRIODES SCRAPÉES ===")
|
|
|
|
# Trouver tous les fichiers CSV
|
|
periods_dir = "data/courses/periods"
|
|
csv_files = glob.glob(os.path.join(periods_dir, "courses_*.csv"))
|
|
|
|
logging.info(f"Nombre de fichiers à combiner: {len(csv_files)}")
|
|
|
|
if not csv_files:
|
|
logging.error("Aucun fichier trouvé !")
|
|
return None
|
|
|
|
# Combiner tous les fichiers
|
|
all_data = []
|
|
|
|
for file in tqdm(csv_files, desc="Combinaison des fichiers"):
|
|
try:
|
|
df = pd.read_csv(file, encoding='utf-8-sig')
|
|
all_data.append(df)
|
|
except Exception as e:
|
|
logging.warning(f"Erreur pour {file}: {e}")
|
|
|
|
if not all_data:
|
|
logging.error("Aucune donnée à combiner !")
|
|
return None
|
|
|
|
# Fusionner toutes les données
|
|
combined_df = pd.concat(all_data, ignore_index=True)
|
|
|
|
logging.info(f"Courses combinées: {len(combined_df)}")
|
|
|
|
# Nettoyer les données
|
|
# Supprimer les doublons
|
|
combined_df = combined_df.drop_duplicates()
|
|
|
|
logging.info(f"Après suppression des doublons: {len(combined_df)}")
|
|
|
|
# Créer le répertoire de sortie
|
|
output_dir = "data/courses"
|
|
os.makedirs(output_dir, exist_ok=True)
|
|
|
|
# Sauvegarder le fichier combiné
|
|
output_file = os.path.join(output_dir, "courses_list_combined.csv")
|
|
combined_df.to_csv(output_file, index=False, encoding='utf-8-sig')
|
|
|
|
logging.info(f"Fichier sauvegardé: {output_file}")
|
|
|
|
# Statistiques
|
|
logging.info("\n=== STATISTIQUES ===")
|
|
logging.info(f"Courses totales: {len(combined_df)}")
|
|
|
|
if 'date' in combined_df.columns:
|
|
# Analyser les dates
|
|
dates = combined_df['date'].value_counts()
|
|
logging.info(f"Dates uniques: {len(dates)}")
|
|
|
|
if 'lieu' in combined_df.columns:
|
|
locations = combined_df['lieu'].value_counts()
|
|
logging.info(f"Lieux uniques: {len(locations)}")
|
|
|
|
if 'resultats_url' in combined_df.columns:
|
|
has_result = combined_df['resultats_url'].notna() & (combined_df['resultats_url'] != '')
|
|
logging.info(f"Courses avec URL de résultats: {has_result.sum()}/{len(combined_df)}")
|
|
|
|
if 'fiche_detail' in combined_df.columns:
|
|
has_fiche = combined_df['fiche_detail'].notna() & (combined_df['fiche_detail'] != '')
|
|
logging.info(f"Courses avec fiche detail: {has_fiche.sum()}/{len(combined_df)}")
|
|
|
|
return combined_df
|
|
|
|
if __name__ == "__main__":
|
|
df = combine_periods()
|
|
|
|
if df is not None:
|
|
logging.info("\n✅ Combinaison terminée avec succès!")
|
|
logging.info(f"💡 Prêt pour l'extraction des résultats")
|