![](https://www.codeandcortex.fr/wp-content/uploads/2024/01/interface-iramuteq-720x458.png)
Introduction
Dans cet article, nous explorons la création d’un script Python conçu pour transformer automatiquement des corpus de presse au format HTML, provenant d’Europresse, en un format compatible avec le logiciel d’analyse textuelle IRAMUTEQ.
Ce script est une réponse « aux défis » posés par les diverses structures de fichiers rencontrées.
Édite 12/01/2024 => Ici le script version 2
Contexte et problématique
Lors de l’exportation depuis Europresse, les fichiers HTML ne présentent pas une structure uniforme, rendant difficile l’identification automatique des éléments clés comme le nom du journal, la date, l’auteur, le titre, le chapeau (chapô), etc.
La variabilité et le manque de clarté de la structure du « chapeau » par exemple compliquent davantage cette tâche. On aurait aimer trouver une structure éditoriale classique du type :
- Nom du journal
- Date
- Auteur
- Titre
- Sous-titre
- Chapeau (Chapô)
- Texte-article
- Illustration(s)-note(s)
Décryptage du fichier HTML : Identification et exclusion des balises non pertinentes
Cette étape initiale d’analyse du code source du fichier HTML est cruciale pour identifier toutes les balises contenant des informations non essentielles à notre objectif.
Voici un aperçu des balises spécifiques qui seront exclues du processus d’importation.
<head>
<div class="rdp__attachnews">
<div class="ImageAttach">
<div class="ImageAttach">
<div class="ImageAttachFont">
<a name="complement"></a>
<div id="entityList">
<div class="icon-logo-container">
<div class="Doc-LegalInfo">
<div id="divPubliC" class="rdp__certificat">
<div class="rdp__DocPublicationName">
<span class="DocPublicationName">
<div class="rdp__DocHeader">
<span class="DocHeader">
<div class="apd-wrapper">
<div class="apd-doc">
<div class="apd-title"><span class="apd-label">
<div class="apd-sources">
<span class="source-name-APD">
<aside>
<footer>
<img class="sm-margin-bottom">
Un atout majeur du script réside dans sa capacité à éliminer les données présentes dans l’en-tête de l’article, similaires à la balise « head » en HTML, ainsi que tout contenu situé en bas de l’article, y compris les « notes » et « illustrations », qui s’apparentent à la zone « footer » en HTML.
Pour que le script fonctionne 😉
Pour commencer, assurez-vous de disposer d’un environnement Python 3 sur votre machine. Ensuite, installez la bibliothèque BeautifulSoup4 en utilisant la commande pip install BeautifulSoup4
.
Une fois cela fait, intégrez le code du script dans le fichier main.py
de votre projet.
Il est important de personnaliser la fin du script en y indiquant le chemin d’accès à votre fichier HTML.
# Exemple d'utilisation
chemin_html = '/chemin/vers/votre/fichier/monfichier.html'
chemin_txt = '/chemin/vers/votre/fichier/monfichier.txt'
extraire_texte_html(chemin_html, chemin_txt)
Si vous utilisez un Mac, une astuce pratique consiste à ouvrir le « Terminal » et à y glisser-déposer votre fichier afin d’en récupérer facilement le chemin complet.
Comme le fichier texte n’existe pas encore (étant donné que le script n’a pas été exécuté), vous pouvez indiquer le même chemin d’accès que celui de votre fichier HTML, en veillant simplement à changer l’extension du fichier de .html par .txt.
Variable : Nom de l’auteur
Ce script est une version améliorée par rapport à un traitement initial réussi sur un seul article.
Une modification notable est l’omission du nom de l’auteur en raison de son placement et formatage incohérents dans les fichiers HTML, rendant cette information peu fiable pour l’analyse. J’ai opté pour ne pas intégrer le nom de l’auteur dans le processus d’importation des données. Dans les fichiers HTML : parfois il apparaît en tête d’article, d’autres fois en conclusion, ou même intégré de manière indistincte au sein du texte. De plus, la présence d’articles co-rédigés complexifie davantage la situation, générant des noms d’auteurs parfois confus et peu exploitables pour une analyse structurée.
Il est donc important de noter que le script, tel qu’il est conçu actuellement, ne récupère et n’affiche pas les noms des auteurs.
Affichage des variables illustratives *
Le script offre la possibilité d’automatiser l’affichage de variables étoilées en premières lignes et inclut une option pour convertir l’ensemble du corpus en minuscules, ce qui est recommandé pour uniformiser l’analyse.
Cette fonctionnalité peut être activée en dé-commentant une ligne spécifique dans le code. (ITAMUTEQ est en capacité de réaliser cette conversion texte en minuscules)
Le script affiche en première ligne de tous les articles les variables étoilées suivantes :
**** *source_nomdujournal *date_2023-12-22 *am_2023-12 *annee_2023
journal_1
, journal_2
, journal_3
contenant des noms de journaux ou des textes associés, afin de les redéfinir pour qu’elles contiennent des noms ou des textes plus courts ou différents.
# Définition initiale des variables
journal_1 = "Le Monde - Édition du 15 Avril"
journal_2 = "The New York Times - International Edition"
journal_3 = "Mon journal qui a un nom de journal beaucoup trop long que je voudrais simplifier"
# Redéfinition des variables avec des noms plus courts
journal_1 = "Le Monde"
journal_2 = "NY Times"
journal_3 = "Mon journal"
# Affichage des nouveaux noms
print(journal_1)
print(journal_2)
print(journal_3)
Par exemple, pour le quotidien « l’Obs » le formatage avec la syntaxe de l’underscore à la place des espaces ainsi que l’ajout de *source_ permet d’obtenir : *source_L_Obs
Suppression des liens web dans les articles
Cette fonctionnalité est particulièrement utile pour traiter du journal comme « La Tribune », où l’abondance de ces liens nécessitait une règle spécifique pour les supprimer.
# Nettoyer les expressions de liens
texte_article = re.sub(r'\(lien : https?://[^)]+\)', '', texte_article)
Gestion des termes spécifiques tels que les « Éditos »
Un problème rencontré est la présence de termes comme « Opinions » ou « La chronique » intégrés dans un élément <div>
sans attribut class
, rendant leur suppression délicate. Je n’ai pas trouvé de solution efficace pour supprimer cette balise. La solution temporaire est d’utiliser un éditeur de texte pour les supprimer manuellement.
Voici une liste des termes qui ne sont pas supprimés (la liste n’est pas exhaustive) : « AUTRE », « Opinions », « La chronique », « Le point de vue », « ANTICIPATION », « Tech », « Une-ECO », « spécial ia france », « Edito »…
Il est important de noter que le script, tel qu’il est conçu actuellement, ne supprime pas ces termes.
Nettoyage et optimisation du corpus
L’exportation depuis Europresse peut entraîner des défauts tels que des mots coupés ou des signatures multiples de l’auteur.
Ces anomalies requièrent un nettoyage manuel. Par exemple le « chapeau » est parfois dupliqué selon la structure utilisée par différents journaux, nécessitant une attention particulière lors du nettoyage.
Ces problèmes proviennent de l’export d’Europresse avec parfois des mots coupés et des retours à la ligne visibles dans le fichier html. Dans ces cas, il s’avère difficile d’apporter des corrections automatiques via le script Python.
Le script dans son intégralité
Le script fonctionne, il a été testé sur différents corpus d’Europresse. Je m’efforce d’optimiser le script, en mettant l’accent sur l’amélioration de la fonctionnalité de nettoyage de textes, dans le but de renforcer son efficacité.
Comme le logiciel IRAMUTEQ, le script est libre d’utilisation, encourageant la collaboration, le partage et l’innovation.
En le partageant avec la communauté, j’espère qu’il évoluera grâce aux contributions de tous, rendant l’analyse de texte plus efficiente en rendant le temps de « toilettage » des corpus Europresse moins chronophage.
############################# # # Titre du Script : [Traitement des corpus Europresse pour IRAMUTEQ] # Auteur : Stéphane Meurisse # Date : 28/12/2023 # # Ce script est un logiciel libre : vous pouvez le redistribuer et/ou le modifier # selon les termes de la GNU (version 3) # # Ce script est distribué dans l'espoir qu'il sera utile, # mais SANS AUCUNE GARANTIE # ############################# 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): # Extraire uniquement la partie avant la virgule (si elle existe) nom_journal_sans_numero = nom_journal.split(",")[0] # Remplacer les espaces et apostrophes par des underscores - supprimer le n° dans le nom nom_journal_sans_numero = re.sub(r"[ ']", "_", nom_journal_sans_numero) return f"*source_{nom_journal_sans_numero}" def extraire_texte_html(chemin_html, chemin_txt): 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() # Extraire et nettoyer le nom du journal span_journal = article.find("span", class_="DocPublicationName") nom_journal_formate = "" if span_journal: nom_journal = span_journal.get_text(strip=True) nom_journal_formate = nettoyer_nom_journal(nom_journal) # Supprimer la balise pour qu'elle n'apparaisse pas dans le texte de l'article span_journal.parent.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() # Concaténer les informations en première ligne info_debut = f"**** {nom_journal_formate} {date_formattee} {am_formattee} {annee_formattee}\n" # 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) # Exemple d'utilisation chemin_html = 'chemin/vers/le/fichier.html' chemin_txt = 'chemin/vers/le/fichier.txt' extraire_texte_html(chemin_html, chemin_txt)
Conclusion
Le script fonctionne efficacement et peut être utilisé même avec un nettoyage minimal du corpus. Une approche itérative peut être bénéfique pour affiner le corpus, en particulier en retravaillant vos mots clés pour cibler des articles spécifiques et répondant mieux à votre problématique.
A l’issue de l’exécution du script, un ajustement manuel du dictionnaire d’Iramuteq reste nécessaire pour certains termes.
Vous pouvez toutefois réaliser cet ajustement par la fonction rechercher / remplacer dans l’éditeur de texte.
Ainsi les deux occurrences « intelligence » « artificielle » peuvent former une seule occurrence grâce à à la syntaxe de l’underscore -> « intelligence_artificielle ».
Pour cette partie de la gestion des expressions je vous encourage à vous référer à la documentation que vous trouverez sur le site d’Iramuteq.
Vos retours, commentaires et signalements de bugs sont vivement encouragés pour améliorer continuellement cet outil 😉
Édite 12/01/2024 => Ici le script version 2
[…] le fonctionnement du script, je vous invite à consulter les deux premiers articles (ici et ici) que j’ai publiés à ce […]
[…] L’outil de statistique IRAMUTEQ exige une préparation spécifique des données textuelles. Pour faciliter ce processus, j’ai élaboré un script Python qui fonctionne localement sur votre ordinateur. Ce script transforme les données extraites du site Europresse en un format compatible avec IRAMUTEQ. Actuellement, le script est testé sur un article individuel, mais il est conçu pour être étendu à un nombre plus important d’articles à l’avenir (coming soon!). […]
[…] correctement. Ce prétraitement peut être réalisé manuellement ou à l’aide de ce script (article 1 – article […]
[…] 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) Promis ! dans la prochaine version du script, […]