#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Script pour lire et analyser le fichier Excel contenant les métadonnées des lettres de Jules Berton. Auteur: Assistant IA Date: Septembre 2025 """ import pandas as pd import os import json from pathlib import Path from datetime import datetime def read_excel_file(excel_path): """ Lit le fichier Excel et retourne un DataFrame avec les métadonnées des lettres. Args: excel_path (str): Chemin vers le fichier Excel Returns: pandas.DataFrame: DataFrame contenant les données du fichier Excel """ try: # Essayer de lire avec différents moteurs try: df = pd.read_excel(excel_path, engine='openpyxl') print(f"✓ Fichier Excel lu avec succès (moteur: openpyxl)") except: try: df = pd.read_excel(excel_path, engine='xlrd') print(f"✓ Fichier Excel lu avec succès (moteur: xlrd)") except: df = pd.read_excel(excel_path) print(f"✓ Fichier Excel lu avec succès (moteur par défaut)") print(f"📊 Dimensions du fichier: {df.shape[0]} lignes × {df.shape[1]} colonnes") return df except FileNotFoundError: print(f"❌ Erreur: Le fichier '{excel_path}' n'a pas été trouvé.") return None except Exception as e: print(f"❌ Erreur lors de la lecture du fichier Excel: {e}") return None def analyze_excel_structure(df): """ Analyse la structure du DataFrame et affiche des informations sur les colonnes. Args: df (pandas.DataFrame): DataFrame à analyser """ if df is None: return print("\n📋 STRUCTURE DU FICHIER EXCEL") print("=" * 50) # Informations générales print(f"Nombre total de lignes: {len(df)}") print(f"Nombre total de colonnes: {len(df.columns)}") # Liste des colonnes print("\n📝 COLONNES DISPONIBLES:") for i, col in enumerate(df.columns, 1): print(f"{i:2d}. {col}") # Aperçu des premières lignes print("\n👀 APERÇU DES PREMIÈRES LIGNES:") print(df.head().to_string()) # Informations sur les types de données print("\n🔢 TYPES DE DONNÉES:") for col in df.columns: print(f"{col}: {df[col].dtype}") # Statistiques sur les valeurs manquantes print("\n❓ VALEURS MANQUANTES:") missing_data = df.isnull().sum() for col in df.columns: if missing_data[col] > 0: percentage = (missing_data[col] / len(df)) * 100 print(f"{col}: {missing_data[col]} ({percentage:.1f}%)") def extract_letter_info(df): """ Extrait et structure les informations sur chaque lettre. Args: df (pandas.DataFrame): DataFrame contenant les métadonnées Returns: list: Liste de dictionnaires contenant les informations de chaque lettre """ if df is None: return [] letters_info = [] print("\n📮 EXTRACTION DES INFORMATIONS DES LETTRES") print("=" * 50) for index, row in df.iterrows(): letter_info = {} # Parcourir toutes les colonnes et extraire les données for col in df.columns: value = row[col] # Nettoyer les valeurs NaN if pd.isna(value): value = None elif isinstance(value, str): value = value.strip() letter_info[col] = value letter_info['index'] = index letters_info.append(letter_info) print(f"✓ {len(letters_info)} lettres extraites") return letters_info def save_to_json(data, output_path): """ Sauvegarde les données extraites en format JSON. Args: data (list): Données à sauvegarder output_path (str): Chemin de sortie pour le fichier JSON """ try: with open(output_path, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=2, default=str) print(f"✓ Données sauvegardées dans: {output_path}") except Exception as e: print(f"❌ Erreur lors de la sauvegarde: {e}") def check_files_existence(letters_info, base_path): """ Vérifie l'existence des fichiers de transcription et d'images pour chaque lettre. Args: letters_info (list): Liste des informations des lettres base_path (str): Chemin de base du projet """ print("\n🔍 VÉRIFICATION DE L'EXISTENCE DES FICHIERS") print("=" * 50) transcriptions_path = Path(base_path) / "transcriptions" images_path = Path(base_path) / "lettres_scannees" for letter in letters_info: # Essayer d'identifier la date dans les données date_found = None # Chercher une colonne qui pourrait contenir la date for key, value in letter.items(): if value and isinstance(value, (str, datetime)): if isinstance(value, datetime): date_found = value.strftime("%Y-%m-%d") break elif isinstance(value, str) and len(value) >= 8: # Essayer de parser différents formats de date try: # Format YYYY-MM-DD if '-' in value and len(value.split('-')) == 3: parts = value.split('-') if len(parts[0]) == 4: date_found = value[:10] # Prendre les 10 premiers caractères break except: continue if date_found: # Vérifier transcription transcription_file = transcriptions_path / f"{date_found}.md" has_transcription = transcription_file.exists() # Vérifier images image_pattern = f"{date_found} *.jpg" image_files = list(images_path.glob(image_pattern)) has_images = len(image_files) > 0 letter['date_parsed'] = date_found letter['has_transcription'] = has_transcription letter['has_images'] = has_images letter['image_count'] = len(image_files) status = "📝" if has_transcription else "❌" status += " 🖼️" if has_images else " ❌" print(f"{date_found}: {status} (images: {len(image_files)})") else: letter['date_parsed'] = None letter['has_transcription'] = False letter['has_images'] = False letter['image_count'] = 0 print(f"Ligne {letter['index']}: ❌ Date non identifiée") def main(): """Fonction principale du script.""" # Chemin du fichier Excel excel_file = "Jules Berton - lettres, dates et lieux.xlsx" base_path = Path(__file__).parent excel_path = base_path / excel_file print("🔍 LECTURE DES MÉTADONNÉES DES LETTRES DE JULES BERTON") print("=" * 60) print(f"📁 Répertoire de travail: {base_path}") print(f"📊 Fichier Excel: {excel_file}") # Vérifier que le fichier existe if not excel_path.exists(): print(f"❌ Le fichier {excel_file} n'existe pas dans le répertoire courant.") print(f" Chemin recherché: {excel_path}") return # Lire le fichier Excel df = read_excel_file(excel_path) if df is None: return # Analyser la structure analyze_excel_structure(df) # Extraire les informations des lettres letters_info = extract_letter_info(df) # Vérifier l'existence des fichiers check_files_existence(letters_info, base_path) # Sauvegarder en JSON output_json = base_path / "lettres_metadata.json" save_to_json(letters_info, output_json) # Statistiques finales print(f"\n📊 STATISTIQUES FINALES") print("=" * 30) total_letters = len(letters_info) with_transcription = sum(1 for l in letters_info if l.get('has_transcription', False)) with_images = sum(1 for l in letters_info if l.get('has_images', False)) print(f"Total des lettres dans Excel: {total_letters}") print(f"Lettres avec transcription: {with_transcription}") print(f"Lettres avec images: {with_images}") print(f"Lettres complètes (texte + images): {sum(1 for l in letters_info if l.get('has_transcription', False) and l.get('has_images', False))}") if __name__ == "__main__": main()