Code source de main

# SmartWatch est un programme permettant l'extraction d'horaires d'ouverture par LLM depuis des sites web,
# et leur comparaison avec des données de référence issues de data.grandlyon.com.
#
# Chaque module de ce projet est documenté sur sa page,
# accessible par un lien indiqué au début de chaque fichier source :
#
# https://datagora-erasme.github.io/smart_watch/index.html

import time

from src.smart_watch.core.ConfigManager import ConfigManager
from src.smart_watch.core.ErrorHandler import (
    ErrorCategory,
    ErrorSeverity,
    handle_errors,
)
from src.smart_watch.core.Logger import create_logger
from src.smart_watch.core.StatsManager import StatsManager
from src.smart_watch.processing import (
    ComparisonProcessor,
    DatabaseProcessor,
    LLMProcessor,
    MarkdownProcessor,
    SetupProcessor,
    URLProcessor,
)
from src.smart_watch.reporting import ReportManager
from src.smart_watch.utils import MarkdownCleaner


[docs] class HoraireExtractor: """Classe principale pour l'extraction et le traitement d'horaires."""
[docs] def __init__(self): """Initialise l'extracteur""" # A. Charger de la configuration self.config = ConfigManager() # Vérification de la configuration if not self.config.validate(): raise ValueError("Configuration invalide") # Initialisation du logger self.logger = create_logger(module_name="Main") # Affichage de la configuration self.config.display_summary() # B. Instancier les processeurs principaux avec la configuration self.db_processor = DatabaseProcessor(self.config, self.logger) self.setup_processor = SetupProcessor(self.config, self.logger) self.url_processor = URLProcessor(self.config, self.logger) self.markdown_cleaner = MarkdownCleaner(self.config, self.logger) self.markdown_processor = MarkdownProcessor(self.config, self.logger) self.llm_processor = LLMProcessor(self.config, self.logger) self.comparison_processor = ComparisonProcessor(self.config, self.logger) self.report_manager = ReportManager(self.config, self.logger) self.stats_manager = StatsManager(self.config, self.logger) self.logger.info("HoraireExtractor initialisé")
# C. Exécuter le pipeline
[docs] @handle_errors( category=ErrorCategory.CONFIGURATION, severity=ErrorSeverity.HIGH, user_message="Erreur lors de l'exécution du pipeline", ) def run(self): """Exécute le pipeline d'extraction complet""" self.logger.section("DÉBUT PIPELINE EXTRACTION HORAIRES") start_time = time.time() try: # 1. Création de la base de données db_manager = self.db_processor.create_database() # Vérifier que le manager de BDD a bien été créé if not db_manager: self.logger.critical( "Le gestionnaire de base de données n'a pas pu être initialisé. Arrêt du pipeline." ) return # 2. Chargement des données, préparation de l'exécution execution_id = self.setup_processor.setup_execution(self.db_processor) # Traitement - Utiliser db_processor partout pour la cohérence # 3. Extraction des URLs self.url_processor.process_urls(self.db_processor, execution_id) # 4. Nettoyage du contenu Markdown brut self.markdown_cleaner.process_markdown_cleaning( self.db_processor, execution_id ) # 5. Filtrage sémantique du Markdown (par embeddings) self.markdown_processor.process_markdown_filtering( self.db_processor, execution_id ) # 6. Extraction des horaires via LLM self.llm_processor.process_llm_extractions(self.db_processor, execution_id) # 7. Comparaison des horaires extraits self.comparison_processor.process_comparisons(self.db_processor) # 8. Génération et envoi du rapport self.report_manager.generate_and_send_report(execution_id) # Log interne au programme : Affichage des statistiques self.stats_manager.display_stats() # Log interne au programme : Résumé final processing_time = time.time() - start_time self.logger.info(f"Pipeline terminé en {processing_time:.2f}s") self.logger.section("FIN PIPELINE EXTRACTION HORAIRES") except Exception as e: processing_time = time.time() - start_time self.logger.error(f"Pipeline échoué après {processing_time:.2f}s: {e}") raise
[docs] @handle_errors( category=ErrorCategory.UNKNOWN, severity=ErrorSeverity.CRITICAL, user_message="Erreur dans le programme principal", reraise=True, ) def main(): """Point d'entrée principal.""" extractor = HoraireExtractor() # C. Exécuter le pipeline extractor.run()
if __name__ == "__main__": main()