#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Script pour analyser la fréquence des mots dans un fichier livre.org et générer un nuage de mots coloré en tons pastels. Ce script: 1. Lit le fichier livre.org 2. Extrait le texte en ignorant les métadonnées et les commentaires 3. Compte la fréquence des mots 4. Sauvegarde les 500 mots les plus fréquents dans un fichier CSV 5. Génère un nuage de mots en SVG et PNG avec des couleurs pastel aléatoires """ import re import os import csv import random import argparse import numpy as np import matplotlib.pyplot as plt from collections import Counter from wordcloud import WordCloud import matplotlib.colors as mcolors # Définir les arguments en ligne de commande parser = argparse.ArgumentParser(description='Analyser la fréquence des mots dans un fichier Org-mode.') parser.add_argument('dossier', nargs='?', help='Le chemin du dossier contenant le fichier livre.org. Si aucun dossier n\'est spécifié, le dossier courant sera utilisé.', default=os.getcwd()) args = parser.parse_args() # Chemin vers le fichier livre.org fichier_livre = f"{args.dossier}/livre.org" # Liste des mots vides (stopwords) en français stopwords = set([ "le", "la", "les", "un", "une", "des", "du", "de", "d'", "l'", "et", "ou", "où", "à", "au", "aux", "ce", "ces", "cette", "cet", "il", "ils", "elle", "elles", "nous", "vous", "je", "tu", "on", "son", "sa", "ses", "leur", "leurs", "mon", "ma", "mes", "ton", "ta", "tes", "que", "qui", "quoi", "dont", "pour", "par", "dans", "sur", "sous", "avec", "sans", "en", "y", "est", "sont", "était", "étaient", "sera", "seront", "a", "ont", "avait", "avaient", "aura", "auront", "plus", "moins", "très", "peu", "beaucoup", "trop", "pas", "ne", "n'", "si", "comme", "mais", "ou", "et", "donc", "car", "quand", "lorsque", "puis", "ensuite", "alors", "ainsi", "aussi", "même", "tout", "tous", "toute", "toutes", "autre", "autres", "certain", "certains", "certaine", "certaines", "tel", "tels", "telle", "telles", "ceci", "cela", "ça", "c'", "s'", "d'", "l'", "qu'", "n'", "m'", "t'", "se", "me", "te", "lui", "leur", "y", "en", "là", "ici", "voici", "voilà", "ci", "là", "cet", "cette", "ces", "celui", "celle", "ceux", "celles", "celui-ci", "celle-ci", "ceux-ci", "celles-ci", "celui-là", "celle-là", "ceux-là", "celles-là" ]) def generate_pastel_color(): """Génère une couleur pastel aléatoire en format RGB.""" # NOTE: PIL's ImageDraw requires integer RGB values (0-255), not floats. # La version précédente retournait des valeurs flottantes entre 0.6 et 0.9, # ce qui causait une erreur: 'float' object cannot be interpreted as an integer # Générer des valeurs RGB entre 153 et 229 (0.6*255 et 0.9*255) pour obtenir des tons pastels # tout en convertissant en entiers pour la compatibilité avec PIL r = int(random.uniform(0.6, 0.9) * 255) g = int(random.uniform(0.6, 0.9) * 255) b = int(random.uniform(0.6, 0.9) * 255) return (r, g, b) def extract_text_from_org(file_path): """ Extrait le texte d'un fichier org-mode en ignorant les métadonnées et les commentaires. """ with open(file_path, 'r', encoding='utf-8') as file: content = file.read() # Supprimer les blocs de commentaires content = re.sub(r'#\+begin_comment.*?#\+end_comment', '', content, flags=re.DOTALL | re.IGNORECASE) # Supprimer les lignes de métadonnées (commençant par #+) content = re.sub(r'^\s*#\+.*$', '', content, flags=re.MULTILINE) # Supprimer les lignes de propriétés content = re.sub(r'^\s*:.*:.*$', '', content, flags=re.MULTILINE) # Supprimer les titres de chapitres (lignes commençant par * ou **) content = re.sub(r'^\s*\*+.*$', '', content, flags=re.MULTILINE) # Supprimer les liens org-mode [[...][...]] et [[...]] content = re.sub(r'\[\[.*?\]\](?:\[.*?\])?', '', content) # Supprimer les caractères spéciaux et la ponctuation content = re.sub(r'[^\w\s]', ' ', content) # Convertir en minuscules content = content.lower() return content def count_word_frequencies(text): """ Compte la fréquence des mots dans un texte. Ignore les mots vides (stopwords) et les mots de moins de 3 caractères. """ # Diviser le texte en mots words = re.findall(r'\b\w+\b', text) # Filtrer les mots courts et les stopwords filtered_words = [word for word in words if len(word) >= 3 and word not in stopwords] # Compter les fréquences word_counts = Counter(filtered_words) return word_counts def save_to_csv(word_counts, output_path, limit=500): """ Sauvegarde les mots les plus fréquents dans un fichier CSV. """ # Obtenir les mots les plus fréquents most_common = word_counts.most_common(limit) # Écrire dans le fichier CSV with open(output_path, 'w', newline='', encoding='utf-8') as csvfile: writer = csv.writer(csvfile) writer.writerow(['Mot', 'Fréquence']) for word, count in most_common: writer.writerow([word, count]) print(f"Les {limit} mots les plus fréquents ont été sauvegardés dans {output_path}") def generate_wordcloud(word_counts, output_svg, output_png): """ Génère un nuage de mots en SVG et PNG avec des couleurs pastel aléatoires. """ # Fonction pour attribuer des couleurs pastel aléatoires aux mots def color_func(word, font_size, position, orientation, random_state=None, **kwargs): return generate_pastel_color() # Créer le nuage de mots wordcloud = WordCloud( width=1200, height=800, background_color='white', max_words=500, color_func=color_func, prefer_horizontal=0.9, relative_scaling=0.5 ).generate_from_frequencies(word_counts) # Sauvegarder en SVG plt.figure(figsize=(12, 8), dpi=300) plt.imshow(wordcloud, interpolation='bilinear') plt.axis('off') plt.tight_layout(pad=0) plt.savefig(output_svg, format='svg', bbox_inches='tight') # Sauvegarder en PNG plt.savefig(output_png, format='png', bbox_inches='tight') plt.close() print(f"Nuage de mots sauvegardé en SVG: {output_svg}") print(f"Nuage de mots sauvegardé en PNG: {output_png}") def main(): # Extraire le texte du fichier livre.org print(f"Analyse du fichier: {fichier_livre}") text = extract_text_from_org(fichier_livre) # Compter les fréquences des mots word_counts = count_word_frequencies(text) # Définir les chemins de sortie csv_output = f"{args.dossier}/frequence_mots_top500.csv" svg_output = f"{args.dossier}/nuage_mots.svg" png_output = f"{args.dossier}/nuage_mots.png" # Sauvegarder les résultats save_to_csv(word_counts, csv_output) generate_wordcloud(word_counts, svg_output, png_output) print("Analyse de fréquence des mots terminée avec succès!") if __name__ == "__main__": main()