Transformer les fichiers HTML Europresse au format IRAMUTEQ avec Python

T

Préparer un corpus pour IRAMUTEQ avec un script Python

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!).

À propos d’IRAMUTEQ

Développé par Pierre Ratinaud, Maître de Conférences en Sciences de l’Éducation (Laboratoire LERASSLaboratoire d’Études et de Recherches Appliquées en Sciences Sociales – Université de Toulouse 3 – Paul Sabatier).
IRAMUTEQ est un logiciel d’analyse textuelle lexicométrique libre, disponible pour Mac et PC (attention à bien respecter la procédure installation et notamment d’utiliser la version de R préconisée).
Fonctionnant sur le logiciel R et le langage Python, il permet de réaliser des analyses textuelles approfondies. Des tutoriels sont accessibles sur le site web, et des vidéos explicatives sur son interface et son fonctionnement sont disponibles sur YouTube.

Europresse en bref

Europresse, accessible principalement aux universitaires et étudiants, offre un accès à l’ensemble de la presse Locale, Nationale et Internationale. L’accès aux ressources est gratuit pour les étudiants / enseignants avec les restrictions liées à leur université.
Par exemple, l’Université Toulouse – Jean-Jaurès limite l’accès à 40 utilisateurs simultanés.
Le mode classique dénommé « étudiant » permet d’exporter des articles en formats PDF ou RSI, qui ne sont pas adaptés pour notre objectif. Cependant, en se connectant en mode « classique », il est possible d’exporter les résultats de recherche en format HTML, plus utile pour notre projet qui vise à automatiser le formatage du fichier HTML en fichier texte (.txt) selon les exigences du logiciel IRAMUTEQ.

Configurer l’environnement Python

Pour utiliser le script, vous devez installer Python 3 et configurer un environnement virtuel sur votre ordinateur. Bien que je n’aborde pas ici les détails de l’installation, vous pouvez utiliser un IDE « Integrated Development Environment » (Environnement de Développement Intégré – éditeur de code Python) pour Python, comme Pycharm (gratuit) ou Visual Studio Code (gratuit), pour faciliter le développement, la modification et l’exécution du script.

Utilisation de BeautifulSoup 4

BeautifulSoup 4, importé sous le nom bs4 (dans le script), joue un rôle crucial dans ce script. Il permet d’analyser et de manipuler le contenu HTML, en facilitant l’extraction de texte et la suppression de balises inutiles. Avec des méthodes comme find() et get_text(), ce script isole et extrait des informations spécifiques à partir de fichiers HTML, tout en gérant efficacement la structure des données pour les adapter aux besoins d’IRAMUTEQ. Cette bibliothèque devra être importé avant de lancer le script, elle n’est pas native dans Python3.
Voici comment le faire :
Ouvrez Psycharm ou Visaul Studio Code
Créez un nouveau projet dans lequel vous déposerez votre fichier « europresse.html »
Utilisez le mode « Terminal » de l’IDE.
Installez BeautifulSoup en exécutant la commande suivante : pip install beautifulsoup4

Ne vous découragez pas si cela ne fonctionne pas ! Laissez vous le temps de découvrir l’éditeur de code (Psycharm, Visual Studio Code, ou autre…)

Analyse et traitement du fichier HTML d’Europresse

L’étape initiale consiste à examiner la structure HTML du fichier.
En affichant le fichier dans un navigateur et en consultant son code source (clic droit, afficher le code source), il est possible d’identifier les balises à exclure ou modifier ou déplacer.
Bien que la structure (code html) du fichier HTML d’Europresse puisse paraître complexe (je dirai « Touffu ! »), l’objectif est de le restructurer pour répondre aux exigences d’IRAMUTEQ et à vos besoins spécifiques.

Le script que je propose réalise cette tâche, facilitant ainsi la transformation des fichiers HTML en fichiers texte structurés et compatibles avec IRAMUTEQ.
Voici ce que donne visuellement l’export d’un article au format HTML :

Et voici ce que nous allons obtenir après avoir lancé le script :

Le script nettoie les principales balises inutiles et incompatibles avec le format attendu pour le logiciel IRAMUTEQ.
Le résultat nécessitera un dernier nettoyage (rechercher / remplacer) dans votre éditeur de texte préféré 😉

Comment fonctionne le script ?

Les données textuelles sont chargées à partir du fichier HTML. Ensuite on cherche à ne pas importer certaines balises comme le <head>, et les classes "rdp__attachnews", "Doc-LegalInfo", "rdp__certificat",
"rdp__public-cert", "publiC_lblCertificatIssuedTo", "publiC-lblNodoc",
"apd-wrapper", "icon-logo-container".

# Supprimer la balise <head> et son contenu
    if soup.head:
        soup.head.decompose()

# Rechercher et supprimer spécifiquement la balise <div> contenant "AUTRE"
  divs_autre = soup.find_all("div")
  for div in divs_autre:
      if div.find("p", string=re.compile("AUTRE")):
          div.decompose()

# Extraire le nom du journal
span_journal = soup.find("span", class_="DocPublicationName")
nom_journal = span_journal.get_text(strip=True) if span_journal else ""
nom_journal_formate = f"*source_{nom_journal}"
if span_journal:
    span_journal.decompose()

# Extraire la date 
span_date = soup.find("span", class_="DocHeader") 
date_texte = html.unescape(span_date.get_text()) 
if span_date else "" 
span_date.decompose() 

# Extraire l'auteur p_auteur = soup.find("p", class_="sm-margin-bottomNews") 
auteur = p_auteur.get_text(strip=True) if p_auteur else "" 
auteur_formate = f"*auteur_{auteur}" 
if p_auteur: 
    p_auteur.decompose() 

# Supprimer les autres balises spécifiques 
classes_a_exclure = ["rdp__attachnews", "Doc-LegalInfo", "rdp__certificat", 
                    "rdp__public-cert", "publiC_lblCertificatIssuedTo", "publiC-lblNodoc", 
                    "apd-wrapper", "icon-logo-container", "AUTRE"] 
for classe in classes_a_exclure: 
    for div in soup.find_all("div", class_=classe): 
        div.decompose()

On cherche à formater les balises inutiles qui n’ont pas été supprimées, notamment en placant les variables « * » sur la première ligne.
La première ligne doit avoir un format très précis : **** *variable_nomdujournal *date *annéemois *année *auteur

**** *source_L’Opinion *date_2023-12-22 *am_2023-12 *annee_2023 *auteur_Capucine_Cousin_(L’AGEFI)

Si toutefois vous ne souhaitez pas afficher l’auteur de l’article il est tout à fait possible de le supprimer.
Dans ce script j’ai choisi de d’afficher cette variable. Elle pose toutefois un problème dans un corpus contenant plusieurs articles car le nom de l’auteur selon le journal ne figure pas dans la même balise.

# Concaténer les informations en première ligne 
info_debut = f"**** {nom_journal_formate} {date_formattee} {am_formattee} {annee_formattee} {auteur_formate}\n" 

# Supprimer les lignes vides et ajouter la première ligne avec les variables 
lignes = [ligne for ligne in texte.splitlines() if ligne.strip()] 
texte_sans_lignes_vides = info_debut + '\n'.join(lignes) 

with open(chemin_txt, 'w', encoding='utf-8') as fichier_txt: 
fichier_txt.write(texte_sans_lignes_vides)

 

Le Script magique !

Voici le script complet et prêt à l’emploi.
J’espère qu’il vous sera utile pour traiter votre corpus, même si pour l’instant il est limité à un seul article.
Le but de ce script est de réduire autant que possible le travail manuel de formatage. Cependant, vous aurez encore besoin d’effectuer certaines tâches de base, comme utiliser la fonction rechercher/remplacer pour éliminer les doubles espaces ou recoder certains éléments avec des underscores.

from bs4 import BeautifulSoup
import os
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 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')

    # Supprimer la balise <head> et son contenu
    if soup.head:
        soup.head.decompose()

    # Rechercher et supprimer spécifiquement la balise <div> contenant "AUTRE"
    divs_autre = soup.find_all("div")
    for div in divs_autre:
        if div.find("p", string=re.compile("AUTRE")):
            div.decompose()

    # Extraire le nom du journal
    span_journal = soup.find("span", class_="DocPublicationName")
    nom_journal = span_journal.get_text(strip=True) if span_journal else ""
    nom_journal_formate = f"*source_{nom_journal}"
    if span_journal:
        span_journal.decompose()

    # Extraire la date
    span_date = soup.find("span", class_="DocHeader")
    date_texte = html.unescape(span_date.get_text()) if span_date else ""
    span_date.decompose()

    # Formatage de la date
    match = re.search(r'\d{1,2} \w+ \d{4}', date_texte)
    date_formattee = am_formattee = annee_formattee = ""
    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


    # Extraire l'auteur
    p_auteur = soup.find("p", class_="sm-margin-bottomNews")
    auteur = p_auteur.get_text(strip=True) if p_auteur else ""
    # Remplacer les espaces par des underscores dans le nom de l'auteur
    auteur = auteur.replace(" ", "_")
    auteur_formate = f"*auteur_{auteur}"
    if p_auteur:
        p_auteur.decompose()

    # Supprimer les autres balises spécifiques
    classes_a_exclure = ["rdp__attachnews", "Doc-LegalInfo", "rdp__certificat",
                         "rdp__public-cert", "publiC_lblCertificatIssuedTo", "publiC-lblNodoc",
                         "apd-wrapper", "icon-logo-container", "AUTRE"]
    for classe in classes_a_exclure:
        for div in soup.find_all("div", class_=classe):
            div.decompose()

    # Extraire le texte restant de la page HTML
    texte = soup.get_text()

    # Concaténer les informations en première ligne
    info_debut = f"**** {nom_journal_formate} {date_formattee} {am_formattee} {annee_formattee} {auteur_formate}\n"

    # Supprimer les lignes vides et ajouter la première ligne avec les variables
    lignes = [ligne for ligne in texte.splitlines() if ligne.strip()]
    texte_sans_lignes_vides = info_debut + '\n'.join(lignes)

    with open(chemin_txt, 'w', encoding='utf-8') as fichier_txt:
        fichier_txt.write(texte_sans_lignes_vides)

# Exemple d'utilisation
chemin_html = 'chemin/vers/votre/fichier.html' # Remplacez par le chemin de votre fichier HTML
chemin_txt = 'chemin/vers/votre/fichier.txt' # Remplacez par le chemin où vous voulez enregistrer le fichier texte
extraire_texte_html(chemin_html, chemin_txt)

Conclusion

En conclusion, ce script est actuellement optimisé pour traiter un seul article à la fois. Si vous l’exécutez sur un fichier HTML contenant plusieurs articles, seul le premier sera formaté conformément aux exigences d’IRAMUTEQ.
Cette version sert de test initial pour valider le fonctionnement du script. Des améliorations sont prévues, notamment l’ajout de boucles Python pour étendre automatiquement le traitement à l’ensemble des articles présents dans un fichier.
Ces développements feront l’objet d’un futur article.
En attendant, je vous invite à expérimenter avec ce script et à partager vos retours et suggestions, qui seront très appréciés et contribueront à l’amélioration de cet outil.

MAJ du 01/01/2024 – Le script est disponible ICI !

A propos de l'auteur

Stéphane Meurisse

2 Comments

Stéphane Meurisse