ODS9 en fichier texte : Script Python mis à jour

Partage
ODS9 en fichier texte : Script Python mis à jour

Cet article fait suite à mes précédents billets concernant l’extraction d’un lexique conforme à l’ODS7 et à l’ODS8. Comme l’Officiel du Scrabble® évolue, il est temps de mettre à jour le script Python pour prendre en compte l’ODS9.

Pour rappel, l’objectif de cette démarche reste purement pédagogique : fournir une liste de mots simple au format .txt pour permettre à mes élèves (cycle 4) de travailler sur le développement d’algorithmes (Boggle, Scrabble, Pendu, etc.).

Rappel important

Je précise bien qu’il s’agit ici d’une liste de mots et non d’un dictionnaire. Les mots appartiennent à tout le monde, mais l’utilisation de la base de mots de l’Officiel du Scrabble® pour des produits commerciaux ou distribués est soumise à des règles strictes édictées par la Fédération Internationale de Scrabble Francophone (FISF) et Larousse.

Le script Python

La structure du site listesdemots.net ayant peu changé, le script reste basé sur le même principe : le scraping des pages de mots avec BeautifulSoup. Notez que le nombre de pages peut varier légèrement selon les mises à jour du site source.

import re
import time
import requests
from bs4 import BeautifulSoup

URL_BASE = "https://www.listesdemots.net/touslesmots"
TOTAL_PAGES = 1548
TIMEOUT = 10
PAUSE = 0.3

session = requests.Session()
session.headers.update({
    "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 "
                  "(KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36"
})

def telecharge(url, essais=5):
    for tentative in range(1, essais + 1):
        try:
            r = session.get(url, timeout=TIMEOUT)
            r.raise_for_status()
            return r
        except requests.exceptions.RequestException as e:
            print(f"Erreur {url} : {e} (tentative {tentative}/{essais})")
            if tentative == essais:
                raise
            time.sleep(tentative)

def extrait_mots(html):
    soup = BeautifulSoup(html, "html.parser")
    texte = soup.get_text("\n", strip=True)

    # On récupère le bloc situé entre "Il y a ... mots" et "Pages :"
    m = re.search(r"Il y a \d+ mots\s+(.*?)\s+Pages :", texte, re.S)
    if not m:
        return []

    bloc = m.group(1)
    bloc = bloc.replace("(page 2)", "").replace("(page 3)", "")

    # Mots en capitales, lettres accentuées admises, plus tiret éventuel
    mots = re.findall(r"\b[A-ZÀÂÄÇÉÈÊËÎÏÔÖÙÛÜŸÆŒ-]+\b", bloc)

    return mots

total_mots = 0
vus = set()

with open("dico.txt", "w", encoding="utf-8") as f:
    for i in range(1, TOTAL_PAGES + 1):
        if i == 1:
            url = URL_BASE + ".htm"
        else:
            url = URL_BASE + f"page{i}.htm"

        try:
            r = telecharge(url)
        except Exception:
            print(f"Page {i} ignorée.")
            continue

        mots = extrait_mots(r.text)

        if not mots:
            print(f"Page {i} : aucun mot extrait")
            continue

        ajoutes = 0
        for mot in mots:
            if mot not in vus:
                vus.add(mot)
                f.write(mot + "\n")
                ajoutes += 1

        total_mots += ajoutes
        print(f"page {i} : OK ({ajoutes} ajoutés / total {total_mots})")

        time.sleep(PAUSE)

print(f"Terminé. Total mots uniques : {total_mots}")

Quelques conseils pour l’exécution

  1. Prérequis : Assurez-vous d’avoir Python installé sur votre machine ainsi que les bibliothèques requests et beautifulsoup4.
  2. Exécution : Lancez le script dans un terminal avec python3 script.py.
  3. Fichier de sortie : Le fichier dico.txt sera généré automatiquement dans le même répertoire que votre script.
  4. Stabilité : En cas de coupure réseau, le script comporte une boucle while pour relancer la requête de la page concernée. Soyez patient, le processus peut prendre quelques minutes.

Bon codage à tous, et n’hésitez pas à adapter ce script à vos propres besoins pédagogiques !

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *