Introduction
Avant de plonger dans les détails techniques, voici pour mémo les prérequis pour faire fonctionner le script :
- Environnement virtuel Python : Assurez-vous d’avoir configuré un environnement virtuel Python (le langage python n’est pas installé par défaut sur Mac et PC).
- Installation de BeautifulSoup4 : Cette bibliothèque est indispensable pour le fonctionnement du script (cf article).
- Lancement via un éditeur de code : Utilisez un éditeur de code tel que PyCharm pour exécuter le script. Actuellement, le script n’est pas compilé ni exécutable directement, mais cela pourrait changer dans une version future.
Pour mieux comprendre le fonctionnement du script, je vous invite à consulter les deux premiers articles (ici et ici) que j’ai publiés à ce sujet.
Une interface graphique simplifiée
L’une des améliorations les plus significatives de cette version est l’introduction d’une interface graphique intuitive, éliminant le besoin de manipuler directement le code du script. Cette évolution majeure rend le script plus accessible et plus facile à utiliser pour tous. Auparavant vous deviez compléter ces lignes de codes en spécifiant le chemin d’accès à votre répertoire.
C’est source d’erreur (très) fréquentes et peut pratique.
# Exemple d'utilisation
chemin_html = 'chemin/vers/le/fichier.html'
chemin_txt = 'chemin/vers/le/fichier.txt'
L’interface graphique de ce script apporte donc une « révolution » notable dans la simplicité d’utilisation.
Avec l’ajout d’un bouton « Parcourir« , il devient extrêmement facile de localiser et de sélectionner le fichier HTML que vous souhaitez traiter, directement depuis votre répertoire de fichiers. Ce niveau d’accessibilité assure que même ceux qui ne sont pas familiers avec la programmation peuvent utiliser le script sans difficulté.
Une fois le fichier HTML sélectionné, le bouton « Envoyer » prend en charge l’extraction des données et enregistre automatiquement le fichier texte résultant dans le même répertoire.
Cette automatisation du processus garantit une expérience utilisateur fluide et sans erreur, depuis le moment où vous choisissez votre fichier jusqu’à l’obtention du fichier texte final, prêt à être utilisé dans IRAMUTEQ.
Fonctionnalités et nouveautés
Le script traite les données HTML pour les convertir en un format texte. Il reconstruit la première ligne de chaque article en incluant les variables étoilées nécessaires pour IRAMUTEQ.
Les principales nouveautés sont :
Choix des variables à exporter
Une avancée notable de ce script est la possibilité qu’il vous offre de choisir précisément les variables à exporter.
Vous avez désormais la liberté de sélectionner non seulement le nom du journal, mais aussi le format de la date d’après vos besoins. Que vous ayez besoin de la date complète (année, mois, jour), juste de l’année et du mois, ou uniquement de l’année, le script s’adapte à votre choix. Cette flexibilité est particulièrement utile pour personnaliser l’exportation en fonction des exigences spécifiques de votre analyse.
Champ libre/texte pour variable(s) étoilée(s)
Une fonctionnalité importante de cette version est l’intégration d’un champ de texte libre qui vous permet d’ajouter facilement une variable étoilée à la première ligne de vos données. Le script se charge automatiquement d’ajouter l’astérisque (*), simplifiant ainsi le processus.
Cette fonction est particulièrement utile pour les analyses thématiques où vous filtrez vos données en fonction de mots-clés spécifiques. Imaginez, par exemple, que vous souhaitez extraire des articles contenant le mot « chatgpt » tout en excluant ceux mentionnant « midjourney« .
De même, vous pourriez vouloir séparer la « presse locale » et « nationale » en utilisant des variables étoilées comme *locale et *nationale respectivement, puis fusionner les deux fichiers texte (les deux exports).
Cependant, il est important de rester vigilant sur les éventuels doublons, car certains articles peuvent être publiés à la fois au niveau national et local sans modification.
Gestion du nom du journal
Le script
le script est en licence GNU (V2) dans le même esprit que le logiciel IRAMUTEQ.
Vous pouvez facilement copier et coller le code en utilisant le bouton situé à droite.
import tkinter as tk from tkinter import filedialog, messagebox from tkinter import IntVar from tkinter import StringVar import os from bs4 import BeautifulSoup import re import html from datetime import datetime import locale # Définir la locale pour interpréter les dates en français locale.setlocale(locale.LC_TIME, 'fr_FR') # ou 'fr_FR.utf8' def nettoyer_nom_journal(nom_journal): print(f"Nom du journal avant nettoyage: '{nom_journal}'") # Pour débogage nom_journal_sans_numero = nom_journal.split(",")[0] nom_journal_sans_numero = re.sub(r"[ ']", "_", nom_journal_sans_numero) nom_journal_nettoye = f"*source_{nom_journal_sans_numero}" print(f"Nom du journal après nettoyage: '{nom_journal_nettoye}'") # Pour débogage return nom_journal_nettoye def extraire_texte_html(chemin_html, chemin_txt, variable_suppl_texte, nom_journal_checked, date_annee_mois_jour_checked, date_annee_mois_checked, date_annee_checked, methode_extraction): with open(chemin_html, 'r', encoding='utf-8') as fichier: contenu_html = fichier.read() soup = BeautifulSoup(contenu_html, 'html.parser') articles = soup.find_all('article') texte_final = "" for article in articles: # Suppression des balises non nécessaires for element in article.find_all(["head", "aside", "footer", "img", "a"]): element.decompose() for element in article.find_all("div", class_=["apd-wrapper"]): element.decompose() for element in article.find_all("p", class_="sm-margin-bottomNews"): element.decompose() nom_journal_formate = "" # Valeur par défaut texte_article = article.get_text(" ", strip=True) # Choix de la méthode d'extraction du nom du journal # Méthode classique if methode_extraction == 0: div_journal = article.find("div", class_="rdp__DocPublicationName") if div_journal: span_journal = div_journal.find("span", class_="DocPublicationName") if span_journal: nom_journal = span_journal.get_text(strip=True) nom_journal_formate = nettoyer_nom_journal(nom_journal) # Méthode 2 if methode_extraction == 1: div_journal = article.find("div", class_="rdp__DocPublicationName") if div_journal: span_journal = div_journal.find("span", class_="DocPublicationName") if span_journal: # Obtenir tout le contenu du span comme une liste content_list = list(span_journal.stripped_strings) if content_list: # Prendre le premier élément de la liste, qui devrait être le nom du journal nom_journal = content_list[0] else: # Si la liste est vide, utiliser une chaîne vide nom_journal = "" nom_journal_formate = nettoyer_nom_journal(nom_journal) print("Nom du journal (méthode 2):", nom_journal_formate) # Pour débogage # Suppression du nom du journal du texte de l'article si nécessaire texte_article = texte_article.replace(nom_journal_formate, '').strip() if div_journal: # Vérifier à nouveau si div_journal existe avant d'appeler decompose() div_journal.decompose() # Extraire la date span_date = article.find("span", class_="DocHeader") date_texte = html.unescape(span_date.get_text()) if span_date else "" date_formattee = am_formattee = annee_formattee = "" if span_date: match = re.search(r'\d{1,2} \w+ \d{4}', date_texte) if match: date_str = match.group() try: date_obj = datetime.strptime(date_str, '%d %B %Y') date_formattee = date_obj.strftime('*date_%Y-%m-%d') am_formattee = date_obj.strftime('*am_%Y-%m') annee_formattee = date_obj.strftime('*annee_%Y') except ValueError: pass span_date.decompose() # Extraire le texte de l'article + saut de ligne après le Titre texte_article = "" for p in article.find_all("p", class_="sm-margin-TopNews titreArticleVisu rdp__articletitle"): texte_article += p.get_text(" ", strip=True) + "\n\n" texte_article += article.get_text(" ", strip=True) # Extraire le texte de l'article texte_article = article.get_text(" ", strip=True) # Traiter spécifiquement la balise <p class="sm-margin-TopNews titreArticleVisu rdp__articletitle"> if article.find("p", class_="sm-margin-TopNews titreArticleVisu rdp__articletitle"): titre_article = article.find("p",class_="sm-margin-TopNews titreArticleVisu rdp__articletitle").get_text(strip=True) texte_article = texte_article.replace(titre_article, titre_article + "\n", 1) # Nettoyer les expressions de liens texte_article = re.sub(r'\(lien : https?://[^)]+\)', '', texte_article) # Traitement des lignes pour ajouter un point à la première ligne et supprimer l'espace en début de chaque ligne lignes = texte_article.splitlines() if lignes and not lignes[0].endswith('.'): # Vérifier si la première ligne n'a pas déjà un point lignes[0] += '.' # Ajouter un point à la fin de la première ligne # Supprimer les espaces en début de chaque ligne lignes = [ligne.strip() for ligne in lignes] # Rejoindre les lignes en une seule chaîne de texte texte_article = '\n'.join(lignes) # Conversion de tout le texte en minuscules -> Vous pouvez décommenter ligne du dessous # pour passer le texte en minuscule # texte_article = texte_article.lower() # Construire info_debut basé sur les cases à cocher info_debut = "****" if nom_journal_checked: info_debut += f" {nom_journal_formate}" if date_annee_mois_jour_checked: info_debut += f" {date_formattee}" if date_annee_mois_checked: info_debut += f" {am_formattee}" if date_annee_checked: info_debut += f" {annee_formattee}" if variable_suppl_texte: info_debut += f" *{variable_suppl_texte}" info_debut += "\n" print("Info début:", info_debut) # Afficher info_debut pour débogage # Ajouter le texte traité de chaque article à texte_final texte_final += info_debut + texte_article + "\n\n" # Écrire le texte final dans le fichier de sortie with open(chemin_txt, 'w', encoding='utf-8') as fichier_txt: fichier_txt.write(texte_final) # Fonction pour parcourir et choisir un fichier HTML def parcourir_fichier(): global chemin_fichier_html chemin_fichier_html = filedialog.askopenfilename(filetypes=[("HTML files", "*.html")]) if chemin_fichier_html: label_chemin.config(text=os.path.basename(chemin_fichier_html)) # Fonction pour traiter le fichier HTML sélectionné def traiter_fichier_html(): if chemin_fichier_html: chemin_txt = os.path.splitext(chemin_fichier_html)[0] + '.txt' variable_suppl_texte = variable_suppl.get() print("Variable supplémentaire:", variable_suppl_texte) # Pour débogage # Récupérer les états des cases à cocher nom_journal_checked = options_variables["nom_du_journal"].get() == 1 date_annee_mois_jour_checked = options_variables["date_année_mois_jour"].get() == 1 date_annee_mois_checked = options_variables["date_année_mois"].get() == 1 date_annee_checked = options_variables["date_année"].get() == 1 # Récupérer l'état du bouton radio pour le filtrage des articles courts # doit_filtrer_articles_courts = filtre_articles_courts.get() # Récupérer la méthode d'extraction du nom du journal sélectionnée par l'utilisateur methode_extraction = methode_extraction_nom_journal.get() # Passer ces états à la fonction extraire_texte_html extraire_texte_html(chemin_fichier_html, chemin_txt, variable_suppl_texte, nom_journal_checked, date_annee_mois_jour_checked, date_annee_mois_checked, date_annee_checked, methode_extraction) messagebox.showinfo("Succès", f"Le fichier a été traité et enregistré en tant que : {os.path.basename(chemin_txt)}") else: messagebox.showwarning("Avertissement", "Veuillez d'abord sélectionner un fichier HTML.") root = tk.Tk() root.title("Convertisseur HTML vers TXT") root.geometry("1200x800") # Taille de la fenêtre ajustée # Texte d'introduction avec des retours à la ligne texte_intro = ("Ce script Python vise à convertir les fichiers au format html provenant du site Europresse au format texte (.txt) pour le logiciel IRAMUTEQ.\n" "Le script effectue un nettoyage du corpus et formate la première ligne de chaque article selon les exigences du logiciel.\n\n" "Le script affiche en première ligne de tous les articles les variables étoilées suivantes :\n" "**** *source_nomdujournal *date_2023-12-22 *am_2023-12 *annee_2023\n\n" "Vous pouvez activer les variables ci-dessous et ajouter une variable (champ texte)\n") label_intro = tk.Label(root, text=texte_intro, font=("Arial", 14), wraplength=root.winfo_screenwidth(), justify=tk.CENTER) label_intro.pack(pady=5) # Variables pour les options, créées après l'initialisation de root options_variables = { "nom_du_journal": IntVar(), "date_année_mois_jour": IntVar(), "date_année_mois": IntVar(), "date_année": IntVar() } # Ajout des cases à cocher pour les options frame_options = tk.Frame(root) frame_options.pack(pady=5) for option, var in options_variables.items(): tk.Checkbutton(frame_options, text=option.replace("_", " ").capitalize(), variable=var).pack(side="left") # Champ pour variable supplémentaire variable_suppl = StringVar() tk.Label(root, text="Votre variable supplémentaire (Laisser le champ vide si pas nécessaire) :").pack() entry_variable_suppl = tk.Entry(root, textvariable=variable_suppl) entry_variable_suppl.pack() # extraction du nom du journal - 2 méthodes methode_extraction_nom_journal = IntVar(value=0) # 0 pour la méthode classique, 1 pour la méthode 2 label_methode_extraction = tk.Label(root, text="\nSélectionnez la méthode d'extraction du nom du journal :") label_methode_extraction.pack() radio_button_methode_classique = tk.Radiobutton(root, text="Méthode classique (On touche à rien et on exporte!)", variable=methode_extraction_nom_journal, value=0) radio_button_methode_classique.pack() radio_button_methode_2 = tk.Radiobutton(root, text="Méthode 2 : (conseillée) Texte avant la balise <br> - permet de raccourcir le nom du journal", variable=methode_extraction_nom_journal, value=1) radio_button_methode_2.pack() # Bouton pour parcourir le fichier bouton_parcourir = tk.Button(root, text="Parcourir", command=parcourir_fichier) bouton_parcourir.pack(pady=(root.winfo_screenheight() // 3 - 200, 10)) # Label pour afficher le chemin du fichier sélectionné label_chemin = tk.Label(root, text="Aucun fichier sélectionné") label_chemin.pack(pady=5) # Bouton pour envoyer (traiter) le fichier bouton_envoyer = tk.Button(root, text="Envoyer", command=traiter_fichier_html) bouton_envoyer.pack(pady=5) # Création d'un Frame pour contenir le texte de bas de page frame_bas_page = tk.Frame(root) frame_bas_page.pack(side=tk.BOTTOM, fill=tk.X, pady=50) # Ajout du texte en bas de page texte_bas_page = "#################\nAuteur : Stéphane Meurisse\nVersion : v2 - 10/02/2024 - Licence : GPL v2\n#################" label_bas_page = tk.Label(frame_bas_page, text=texte_bas_page, justify=tk.CENTER) label_bas_page.pack() root.mainloop()
Conclusion
[…] logiciels d’analyse textuelle, tels que IRAMATEQ, propose une lemmatisation de manière automatisée après intégration du […]
[…] Édite 12/01/2024 => Ici le script version 2 […]
[…] YouTube… La prochaine étape consistera à tester le TF-IDF sur un corpus provenant d’Europresse, ce qui représente une difficulté en moins. Je me questionne également sur […]
[…] J’ai développé une interface en Python qui simplifie ce processus, permettant une gestion rapide et efficace des articles en double ou trop courts avant leur importation dans IRaMuTeQ. Il est important de noter que ce script est conçu pour être utilisé avec un corpus Europresse pré-traité pour IRaMuTeQ. Cela signifie que chaque première ligne de chaque article doit être composée de variables étoilées. Le script utilise les « **** » de chaque première ligne pour identifier l’article et scanner le texte à partir de la seconde ligne. Le pré-traitement de votre fichier au format IRaMuTeQ est donc un prérequis pour que le script fonctionne correctement. Ce prétraitement peut être réalisé manuellement ou à l’aide de ce script (article 1 – article 2). […]
[…] pour essayer de réaliser une analyse longitudinale. Pour cela, j’ai utilisé le script d’encodage des articles Europresse pour IRAMUTEQ, en ne gardant que les dates comme variable étoilée, notamment pour essayer de […]
[…] ? Parce que le corpus est formaté avec le script qui prépare les données pour un passage dans le logiciel IRAMUTEQ. (Vous pouvez vous référer aux trois scripts permettant de préparer les données pour IRAMUTEQ) […]
[…] HTML to Text : Cette fonctionnalité convertit les fichiers HTML issus de la base de données Europresse en texte brut, facilitant ainsi l’analyse des articles de presse dans le logiciel IRAMUTEQ ou […]
[…] Une fois l’export réalisé via le site Europresse, nous obtenons un fichier HTML brut, nécessitant un prétraitement pour ne conserver que les balises html pertinentes et le transformer en fichier texte. Je ne reviendrai pas sur cette étape ; vous pouvez vous référer à cet article qui explique comme…. […]