Récemment, j’ai eu besoin de trouver une liste de mots, une liste exhaustive de mots en français. Une telle liste peut avoir plusieurs usages comme, par exemple:
- jouer au scrabble en solitaire
- solutionner automatiquement des grilles de mots-croisés
- etc
Ma recherche sur Internet ne m’a pas permis de trouver un fichier suffisamment complet mais j’ai découvert le programme CeWL qui permet de créer des listes en puisant des mots dans des sites WEB. L’idée est bonne.
CeWL est un logiciel libre écrit en Ruby mais je n’ai aucune connaissance de Ruby. J’ai donc décidé d’utiliser le même concept mais de le réaliser en Python. Mon approche initiale est de puiser tous les mots de Wikipédia en français. Pourquoi Wikipédia? La quantité des textes disponibles est impressionnante et la qualité de leurs textes est excellente (peu d’erreurs orthographiques).
La logique d’un tel programme se résume comme suit:
- visiter toutes (ou du moins plusieurs) pages de Wikipédia français.
- en extraire tous les mots affichés (ne pas tenir compte des mots HTML)
- filtrer pour conserver les mots appropriés au besoin
- éliminer les duplicata
La 1ère étape se fait facilement avec l’utilitaire wget et les 3 suivantes se font facilement en Python. Le résultat de la 1ère étape prendrait la forme de:
wget [options] fr.wikipedia.org | monFiltre > listeDeMots.txt
Le principe de wget est d’analyser une page WEB et de suivre tous les liens qu’elle contient. Chacune de ces pages contient aussi des liens qui en contiennent d’autres. En explorant tous ces liens, on réussit à explorer un site WEB en ne spécifiant qu’un seul point d’entrée.
wget -E -e robots=off -nd -r -l6 -w1 fr.wikipedia.org
La 2ième étape est plus complexe. Le fichier reçu est en langage HTML. On ne veut pas extraire des mots de la syntaxe HTML. Il faut donc localiser le texte affiché à l’intérieur du HTML. Ce pourrait être complexe car le HTML n’est pas simple. Heureusement, Python et le module HTMLParser nous simplifieront la tâche. Il suffit d’utiliser le texte qui se trouve à l’intérieur des balises <body … </body> et à l’extérieur des balises <script … </script> et <a … </a>. Une version simplifiée serait:
class htmlParser( HTMLParser): def handle_starttag( self, tag, attr): enCours.append( tag) def handle_endtag( self, tag): for i in range( len(enCours), 0, -1): if enCours[i-1] == tag: del enCours[i-1] def handle_data( self, data): if ('body' in enCours) and not (('script' in enCours) or ('a' in enCours)): for c in ',.;:/(){}[]|?"%@!$&+=_\t\\': txt2 = txt2.replace( c, ' ') # tous sauf "-\'" mots = txt2.split() for mot in mots: # on met ici certaines exclusions ou contraintes: if mot.isnumeric(): continue # on ne veut pas de nombres mot = mot.lower(): tout en minuscules if not (mot in listeMots): listeMots.append(mot) print( mot)
L’étape 3 dépend des besoins spécifiques. Si on veut des mots pour le Scrabble, on remplacera les lettres accentuées par leur version non-accentuée et on convertira tout en majuscules (ou tout en minuscules).
L’étape 4 est facile à réaliser.
Une version plus complète est disponible ici.
Combien de pages faut-il visiter? La section française de Wikipédia contient près de 2 millions de pages. Faut-il toutes les visiter? Non! ce serait un gaspillage d’électrons libres. Plus on visite des pages moins on découvrira de mots nouveaux. À partir d’un certain point, il n’y aura plus de nouveauté (du moins, c’est ce que je pensais).
Après 20 000 pages (plus de 3Go de trafic), ma liste s’allonge encore (elle est actuellement de plus de 700 000 mots. Malheureusement, j’avais sous-estimé le nombre de noms propres et de noms scientifiques dans les pages Wikipédia. Ma liste contient donc des milliers de noms de fleurs (en français et en latin), des dizaines de milliers de noms d’individus (tel « Éric » « Lapointe »), des centaines de milliers de noms de lieux (tel « Saint-Jean » « Matha ») et des fautes (telle ciconscriptions). Ma 1ère conclusion est que Wikipédia fournit un contenu trop encyclopédique pour mon besoin. Je referai donc le même exercice avec le contenu d’un ensemble de romans. C’est à suivre.
2ième conclusion: ce qui est simple n’est pas nécessairement performant. Le programme présenté plus haut est simple et même trop simple. Un énoncé du genre « if mot in listeMots » semble inoffensif mais lorsque la liste contient plusieurs centaines de milliers de mots, le temps d’exécution de l’énoncé est non-négligeable et devient un goulot d’étranglement. Il existe des techniques plus performantes et ce fera l’objet d’un article futur.