Boîtes à outils

Site réalisé pour le TD de Programmation et Projet Encadré II (L8T04) du master PluriTAL

There is more than one way to do it

Ce site présente des scripts perl dédié à l'extraction d'informations à partir d'un corpus de flux rss, de deux façons différentes, ainsi qu'à l'étiquetage des données ainsi extraites.

Le corpus utilisé consiste en l'intégralité des flux RSS du journal Le Monde de l'année 2013.

RSS (le sens de l'acronyme a varié au cours du temps) est une norme XML servant à décrire des informations organisées de façon chronologiques, typiquement des informations journalistiques, mais aussi des blogs, etc.

Les flux RSS du Monde décrivent des articles du journal avec leur date de publication, leur titre et une description de leur contenu, ainsi que la rubrique à laquelle ils sont rattachés.

Le but du script va être d'extraire ces différentes informations et de classer les articles par rubriques.

Le script d'extraction des données

Arguments

Le script prends deux arguments en entrée. Le premier est le dossier contenant les flux RSS qui doivent être traités. Le deuxième est le dossier de sortie.

C'est la fonction dirz qui se charge de créer le répertoire de sortie et ses trois sous-répertoires s'ils n'existent pas. S'ils existent, la fonction dirz demande à l'utilisateur de confirmer la suppression de ces répertoires.

Si elle est confirmée, dirz fait appel à la fonction rmfolder, qui va parcourir le répertoire, y supprimer chaque fichier, et s'appeler elle-même récursivement sur chacun de ses sous-dossier avant de le supprimer (on ne peut supprimer un dossier que s'il est vide).

Parcours de l'arborescence

Les flux RSS recueillis sont organisés dans une arborescence de dossiers, par mois et par jour du mois. Le moyen le plus simple de traiter cette arborescence sans se préoccuper de sa structure exacte est de partir du principe que tout élément d'un dossier est soit lui-même un dossier, soit un fichier.

Autrement dit, une arborescence de fichier étant elle-même une structure récursive, le moyen le plus simple d'en traiter les éléments est une fonction récursive.

L'essentiel du script se déroule suite à l'appel de la fonction arbo sur le répertoire à traiter.

La fonction va lire le contenu du dossier. Pour chaque élément du dossier, s'il s'agit lui-même d'un dossier, la fonction arbo s'appelle elle-même dessus. Sinon, s'il s'agit d'un fichier, arbo vérifie d'abord qu'il possède l'extension ".xml", et même alors, elle vérifie ensuite qu'il possède bien l'en-tête XML, car certains fichiers du corpus possédant cette extension sont en fait des fichiers HTML. Lorsque c'est le cas, arbo imprime un message d'erreur indigné.

Les fichiers XML quant à eux sont envoyés comme arguments aux deux fonctions d'extraction de données : la fonction pureperl qui va employer uniquement des méthodes basiques, et la fonction rssperl qui va utiliser les fonctions de la librairie XML::RSS.

Extraction des données

Pur perl

La fonction pureperl se base largement sur les expressions régulières qui sont le point fort de perl.

Tout d'abord, la fonction détermine l'encodage du fichier en extrayant cette information de son en-tête.

Puis, ayant ouvert le fichier sous son encodage correct, la fonction en concatène le contenu sur une seule ligne. Elle supprime les espaces entre les balises, et ce pré-traitement terminé, l'extraction de données peut commencer.

Les premières données extraites sont la date et la rubrique

Puis, le titre et la description sont extraits, là encore via une expression régulière.

<item>.*?<title>(.*?)<\/title>.*?<description>(.*?)<\/description>

(les points d'interrogation modifient le comportement du méta-caractère *, qui essaie en temps ordinaire de trouver la correspondance la plus grande possible. C'est le comportement inverse qui est obtenu ici.)

Tant que cette expression régulière trouve des correspondances, elles sont extraites et assignées aux variables $titre et $description.

XML RSS

La fonction rssperl se base sur la librairie XML::RSS de perl, qui offre un ensemble de fonctions permettant de manipuler les flux rss.

À la différence de la fonction précédente, rssperl ne fait pas de prétraitement particulier. Elle crée un objet XML::RSS, qui crée seul la modélisation du fichier au moyen de la méthode parsefile.

Puis elle récupère les différentes informations stockées dans l'objet grâce aux nom des noeuds (balises XML). Ainsi, le titre de la rubrique est récupéré par my $canal = $rss->{'channel'}; my $rubrique=$canal->{'title'};

L'extraction des titres et description des articles se fait au moyen du code suivant :

$titre = $item->{'title'};

$description = $item->{'description'};

rssperl extrait ainsi rigoureusement les mêmes informations que la fonction précedentes.

Traitement des informations extraites

Après l'extraction de ces informations, les deux fonctions pureperl et rssperl se comportent exactement de la même façon.

Tout d'abord, le titre et la description de l'article sont nettoyés au moyen de la fonction nettoyerTexte, qui supprime ou remplace les caractères indésirables et/ou les entités HTML.

Puis, si le titre ou la description n'ont pas encore été rencontrés, ils sont rajoutés dans un dictionnaire, afin d'empêcher l'existence de doublons dans le corpus final.

Ensuite, ils sont concaténés aux variables $xmlitems et textitems, qui, ainsi que l'indiquent leurs noms, sont vides au départ, et reçoivent ensuite l'ensemble des items d'un fichier.

Une fois que tous les items ont été concaténés dans ces variables, ces dernières sont à leur tour concaténées à l'ensemble global des items qui serviront à créer les fichiers de sorties globales.

Notons que la sortie globale en XML est classée par rubrique, il faut donc stocker les items de façon à ce qu'ils soient organisés en rubrique, ce qui est fait au moyen d'un dictionnaire (autrement dit un hash).

Création des fichiers de sortie

C'est la fonction outputting qui va se charger de créer et de gérer les différents fichiers de sortie.

Elle prend en entrée le répertoire de sortie visé, la date de publication du flux rss et le nom du fichier d'où il a été tiré, le nom de la rubrique concernée, et les listes d'items précédemment constituées.

Que ce soit pour la sortie textuelle ou la sortie xml, outputting commence par vérifier si le fichier correspondant à la rubrique traitée existe déjà où non.

Si non, il le crée, avec dans le cas du xml, les informations d'en-tête appropriées.

Une fois le parcours de l'arborescence fini et tous les fichiers traités, les fichiers de sortie globaux sont créés..

On note que les fichiers textuels sont créés très simplement, tandis que les sorties globales XML nécessitent une boucle, afin de classer correctement les items selon chaque rubrique.

La même boucle sert en même temps à parcourir chaque fichier XML afin de rajouter les balises fermantes qui doivent tous les conclure.

On peut vérifier que les fichiers obtenus selon la méthode "pur perl" sont les mêmes que ceux obtenus en utilisant le parseur de XML::RSS grâce à la commande bash suivante :

echo for z in $( ls "sorties/purperl" );

do

diff -sq "sorties/purperl/$z" "sorties/xmlrss/$z";

done

On constate avec bonheur que les deux sorties, bien qu'obtenues selon des méthodes différentes, sont complètement identiques.

There really is more than one way to do it !
.

Tags

Le même script incorpore enfin un appel à une application externe, treetagger, qui permet d'accoller des étiquettes donnant la partie du discours d'un mot à des listes de mots séparées par des sauts de ligne.

Pour ce faire, chaque fichier txt d'un des deux répertoires de sortie (en l'occurrence c'est la sortie "pur perl" qui est utilisée, mais ça n'a absolument aucune importance puisque les sorties sont identiques), est ouvert par la fonction ttagging puis le contenu en est recopié dans un fichier temporaire, où chaque mot n'occupe qu'une ligne, dont le contenu est transmis à treetagger via la commande cat, le tout étant intégré au script perl via la fonction system.

La sortie de treetagger est ensuite redirigée vers un fichier de sortie situé dans le répertoire des sorties étiquetées.

Patrons

Le script

Une fois nos sorties étiquetées obtenues, on peut commencer à en extraire des patrons. C'est là qu'intervient le script d'extraction des patrons.

Ce script relativement court utilise des expressions régulières pour relever dans les fichiers étiquetés des patterns syntaxiques (comme la succession déterminant-nom-adjectif).

Il prend en entrée le nom d'un fichier contenant des patrons syntaxiques ainsi que d'un fichier contenant des phrases étiquetées par tree-tagger.

Le script établit une liste des étiquettes du document étiqueté pris en entrée, puis, pour chaque patron, il cherche à trouver une correspondance totale entre une sous-partie de cette liste et le patron.

Lorsqu'une correspondance est trouvée, le mot correspondant à la position donnée dans la liste des mots du document est relevé dans une variable qui finit par contenir l'intégralité des mots du patron.

Lorsque c'est le cas, la variable est concaténée à la variable output, qui est ensuite imprimé dans un fichier portant le nom du patron relevé.

Les patrons relevés sont généralistes : l'expression VER capture tous les verbes, quel que soit le temps spécifié par tree-tagger.

Exemples de patrons extrait

Patrons extraits du fichier tagged-voyage.txt

Voir le fichier de patrons brut

misc

Fin

Il m'a été impossible de faire fonctionner patron2graphe.exe sur mon ordinateur, parce que ce dernier tourne sous un système d'exploitation unix.

La BàO n° 4 est donc annulée pour des raisons indépendantes de ma volonté.