{"id":106,"date":"2017-08-28T16:30:01","date_gmt":"2017-08-28T16:30:01","guid":{"rendered":"http:\/\/www.technologue.net\/?p=106"},"modified":"2017-11-07T22:16:34","modified_gmt":"2017-11-07T22:16:34","slug":"liste-de-mots","status":"publish","type":"post","link":"http:\/\/www.technologue.net\/?p=106","title":{"rendered":"Liste de mots"},"content":{"rendered":"<p>R\u00e9cemment, j&rsquo;ai eu besoin de trouver une liste de mots, une liste exhaustive de mots en fran\u00e7ais. Une telle liste peut avoir plusieurs usages comme,\u00a0 par exemple:<\/p>\n<ul>\n<li>jouer au scrabble en solitaire<\/li>\n<li>solutionner automatiquement des grilles de mots-crois\u00e9s<\/li>\n<li>etc<\/li>\n<\/ul>\n<p>Ma recherche sur Internet ne m&rsquo;a pas permis de trouver un fichier suffisamment complet mais j&rsquo;ai d\u00e9couvert le programme CeWL qui permet de cr\u00e9er des listes en puisant des mots dans des sites WEB. L&rsquo;id\u00e9e est bonne.<\/p>\n<p>CeWL est un logiciel libre \u00e9crit en Ruby mais je n&rsquo;ai aucune connaissance de Ruby. J&rsquo;ai donc d\u00e9cid\u00e9 d&rsquo;utiliser le m\u00eame concept mais de le r\u00e9aliser en Python. Mon approche initiale est de puiser tous les mots de Wikip\u00e9dia en fran\u00e7ais. Pourquoi Wikip\u00e9dia? La quantit\u00e9 des textes disponibles est impressionnante et la qualit\u00e9 de leurs textes est excellente (peu d&rsquo;erreurs orthographiques).<\/p>\n<p>La logique d&rsquo;un tel programme se r\u00e9sume comme suit:<\/p>\n<ol>\n<li>visiter toutes (ou du moins plusieurs) pages de Wikip\u00e9dia fran\u00e7ais.<\/li>\n<li>en extraire tous les mots affich\u00e9s (ne pas tenir compte des mots HTML)<\/li>\n<li>filtrer pour conserver les mots appropri\u00e9s au besoin<\/li>\n<li>\u00e9liminer les duplicata<\/li>\n<\/ol>\n<p>La 1\u00e8re \u00e9tape se fait facilement avec l&rsquo;utilitaire wget et les 3 suivantes se font facilement en Python. Le r\u00e9sultat de la 1\u00e8re \u00e9tape prendrait la forme de:<\/p>\n<p>wget [options] fr.wikipedia.org | monFiltre &gt; listeDeMots.txt<\/p>\n<p>Le principe de wget est d&rsquo;analyser une page WEB et de suivre tous les liens qu&rsquo;elle contient. Chacune de ces pages contient aussi des liens qui en contiennent d&rsquo;autres. En explorant tous ces liens, on r\u00e9ussit \u00e0 explorer un site WEB en ne sp\u00e9cifiant qu&rsquo;un seul point d&rsquo;entr\u00e9e.<\/p>\n<p>wget -E -e robots=off -nd -r -l6 -w1 fr.wikipedia.org<\/p>\n<p>La 2i\u00e8me \u00e9tape est plus complexe. Le fichier re\u00e7u est en langage HTML. On ne veut pas extraire des mots de la syntaxe HTML. Il faut donc localiser le texte affich\u00e9 \u00e0 l&rsquo;int\u00e9rieur du HTML. Ce pourrait \u00eatre complexe car le HTML n&rsquo;est pas simple.\u00a0 Heureusement, Python et le module HTMLParser nous simplifieront la t\u00e2che. Il suffit d&rsquo;utiliser le texte qui se trouve \u00e0 l&rsquo;int\u00e9rieur des balises &lt;body &#8230; &lt;\/body&gt; et \u00e0 l&rsquo;ext\u00e9rieur des balises &lt;script &#8230; &lt;\/script&gt; et &lt;a &#8230; &lt;\/a&gt;. Une version simplifi\u00e9e serait:<\/p>\n<pre>class htmlParser( HTMLParser):\r\n   def handle_starttag( self, tag, attr):\r\n\u00a0\u00a0  \u00a0\u00a0 enCours.append( tag)\r\n\r\n\u00a0\u00a0 def handle_endtag( self, tag):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 for i in range( len(enCours), 0, -1):\r\n\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0 if enCours[i-1] == tag: del enCours[i-1]\r\n \r\n   def handle_data( self, data):\r\n\u00a0\u00a0\u00a0   if ('body' in enCours) and not (('script' in enCours) or ('a' in enCours)):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0  for c in ',.;:\/(){}[]|?\"%@!$&amp;+=_\\t\\\\': txt2 = txt2.replace( c, ' ') # tous sauf \"-\\'\"\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 mots = txt2.split()\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0  for mot in mots:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0  # on met ici certaines exclusions ou contraintes:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if mot.isnumeric(): continue # on ne veut pas de nombres\r\n             mot = mot.lower(): tout en minuscules\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if not (mot in listeMots):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 listeMots.append(mot)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 print( mot)\r\n<\/pre>\n<p>L&rsquo;\u00e9tape 3 d\u00e9pend des besoins sp\u00e9cifiques. Si on veut des mots pour le Scrabble, on remplacera les lettres accentu\u00e9es par leur version non-accentu\u00e9e et on convertira tout en majuscules (ou tout en minuscules).<\/p>\n<p>L&rsquo;\u00e9tape 4 est facile \u00e0 r\u00e9aliser.<\/p>\n<p>Une version plus compl\u00e8te est disponible ici.<\/p>\n<p>Combien de pages faut-il visiter? La section fran\u00e7aise de Wikip\u00e9dia contient pr\u00e8s de 2 millions de pages. Faut-il toutes les visiter? Non! ce serait un gaspillage d&rsquo;\u00e9lectrons libres. Plus on visite des pages moins on d\u00e9couvrira de mots nouveaux.\u00a0 \u00c0 partir d&rsquo;un certain point, il n&rsquo;y aura plus de nouveaut\u00e9 (du moins, c&rsquo;est ce que je pensais).<\/p>\n<p>Apr\u00e8s 20 000 pages (plus de 3Go de trafic), ma liste s&rsquo;allonge encore (elle est actuellement de plus de 700 000 mots. Malheureusement, j&rsquo;avais sous-estim\u00e9 le nombre de noms propres et de noms scientifiques dans les pages Wikip\u00e9dia. Ma liste contient donc des milliers de noms de fleurs (en fran\u00e7ais et en latin), des dizaines de milliers de noms d&rsquo;individus (tel \u00ab\u00a0\u00c9ric\u00a0\u00bb \u00ab\u00a0Lapointe\u00a0\u00bb), des centaines de milliers de noms de lieux (tel \u00ab\u00a0Saint-Jean\u00a0\u00bb \u00ab\u00a0Matha\u00a0\u00bb) et des fautes (telle ciconscriptions). Ma 1\u00e8re conclusion est que Wikip\u00e9dia fournit un contenu trop encyclop\u00e9dique pour mon besoin. Je referai donc le m\u00eame exercice avec le contenu d&rsquo;un ensemble de romans. C&rsquo;est \u00e0 suivre.<\/p>\n<p>2i\u00e8me conclusion: ce qui est simple n&rsquo;est pas n\u00e9cessairement performant. Le programme pr\u00e9sent\u00e9 plus haut est simple et m\u00eame trop simple. Un \u00e9nonc\u00e9 du genre \u00ab\u00a0if mot in listeMots\u00a0\u00bb semble inoffensif mais lorsque la liste contient plusieurs centaines de milliers de mots, le temps d&rsquo;ex\u00e9cution de l&rsquo;\u00e9nonc\u00e9 est non-n\u00e9gligeable et devient un goulot d&rsquo;\u00e9tranglement. Il existe des techniques plus performantes et ce fera l&rsquo;objet d&rsquo;un article futur.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>R\u00e9cemment, j&rsquo;ai eu besoin de trouver une liste de mots, une liste exhaustive de mots en fran\u00e7ais. Une telle liste peut avoir plusieurs usages comme,\u00a0 par exemple: jouer au scrabble en solitaire solutionner automatiquement des grilles de mots-crois\u00e9s etc Ma recherche sur Internet ne m&rsquo;a pas permis de trouver un fichier suffisamment complet mais j&rsquo;ai &hellip; <\/p>\n<p class=\"link-more\"><a href=\"http:\/\/www.technologue.net\/?p=106\" class=\"more-link\">Continuer la lecture<span class=\"screen-reader-text\"> de &laquo;&nbsp;Liste de mots&nbsp;&raquo;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[15],"tags":[16,13],"_links":{"self":[{"href":"http:\/\/www.technologue.net\/index.php?rest_route=\/wp\/v2\/posts\/106"}],"collection":[{"href":"http:\/\/www.technologue.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.technologue.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.technologue.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.technologue.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=106"}],"version-history":[{"count":3,"href":"http:\/\/www.technologue.net\/index.php?rest_route=\/wp\/v2\/posts\/106\/revisions"}],"predecessor-version":[{"id":159,"href":"http:\/\/www.technologue.net\/index.php?rest_route=\/wp\/v2\/posts\/106\/revisions\/159"}],"wp:attachment":[{"href":"http:\/\/www.technologue.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=106"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.technologue.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=106"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.technologue.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=106"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}