Objectif
L'objectif est d'extraire des patrons morphosyntaxiques à partir des
fichiers produits par Cordial et Treetagger, dans la boîte à
outils 2.
Les patrons exploités sont du type "NOM ADJ", "NOM PREP NOM" et "NOM
NOM" uniquement sur la rubrique "A la Une".
Pour les fichiers Cordial, nous avons utilisé un script Perl. Quant aux
fichiers étiquetés par Treetagger, nous les avons traités par deux
méthodes : un script Perl utilisant le module XML::XPath et une feuille
de style XSLT.
Cordial : Notre extraction
Pour extraire ces patrons des fichiers .cnr produits par Cordial, nous
proposons un script inspiré de celui de Serge Fleury mais qui permet de
rentrer les patrons sans l'utilisation d'expression régulière.
Ce script comporte deux variations, avec et sans sous-programme de gestion des sous-listes d'indices.
Cependant,
nous avons remarqué que la version sans sous-programme, contenant donc
une boucle imbriquée pour l'impression des résultats, est beaucoup plus
lente
d'exécution.
A noter: une ingénieuse utilisation des
quatificateurs
non gourmants qui permet de filtrer la chaîne la plus courte
satisfaisant l'expression régulière.
Voici le script commenté :
#!/usr/bin/perl
#----------------------------------
# EXTRACTION CORDIAL
# usage : extrac_cordial_bouclewhile.pl fichier.cnr liste_des_pos
# exemples : - extrac_cordial.pl fichier.cnr N V ADV
# - extrac_cordial.pl fichier.cnr N PREP N ADJ
#----------------------------------
#----------------------------------
# Récupération des catégories morphosyntaxiques entrés par l'utilisateur
my $sortie =""; # on prépare une variable pour le nom du fichier de sortie
for(my $n=1;$n<=$#ARGV;$n++){
${"etiq$n"} = $ARGV[$n];
$sortie .= ${"etiq$n"};
$sortie .= "_";
}
#----------------------------------
# Ouverture du fichier en lecture
#----------------------------------
open (FICTAG, $ARGV[0]) or die ("probleme sur ouverture de la sortie CORDIAL");
#---------------------------
# Initialisation des listes
#--------------------------
my @malignesegmentee = ();
my @listedetokens = ();
my @listedelemmes = ();
my @listedepos = ();
#-------------------------------------------
# Lecture du fichier de tags ligne par ligne
#-------------------------------------------
while (my $ligne = <FICTAG>) {
#----------------------------------------------------------------------
# On ne s'occupe pas des lignes qui ne respectent pas
# le modèle mot tab mot tab mot
#----------------------------------------------------------------------
if ($ligne =~ /^[^\t]+\t[^\t]+\t[^\t]+$/) {
#-------------------------------------------
# Suppression du caractère de saut de ligne
chomp($ligne);
#-------------------------------------------
# Remplissage des listes
@malignesegmentee = split(/\t/, $ligne);
push(@listedetokens, $malignesegmentee[0]);
push(@listedelemmes, $malignesegmentee[1]);
push(@listedepos, $malignesegmentee[2]);
#-------------------------------------------
}
}
close(FICTAG);
my @listedepos2=();
my @listeindice=();
my @indice=();
#--------------------------------
# 1. on crée une nouvelle liste de pos, en collant à chaque
# pos la lettre 'z' et son indice dans la liste
#---------------------------------
my $i=0;
foreach my $pos(@listedepos){
$pos.=z.$i;
push(@listedepos2, $pos);
$i++;
}
#----------------------------------
# 2. on transforme la liste précédente en une string,
# chaque élément étant séparé par des z (z est un bon séparateur
# car aucun pos ne contient cette lettre)
#----------------------------------
my $string=join(z,@listedepos2);
#-----------------------------------
# 3. j'écris la regexp pour récupérer une liste qui ne contiendra
# que les indices correspondant aux pos recherchés. A noter, l'utilisation
# du quantificateur non gourmand '?', indispensable pour filtrer
# la sous-chaîne la plus courte entre le nom de la catégorie
# grammaticale et l'indice.
#-----------------------------------
my $er ="";
for(my $c = 1;$c <= $#ARGV; $c++){
$temp = ${"etiq$c"};
$er.=" $temp [^z]*?z([0-9]+)z";
}
$er=~s/ //g;
# L'idée est de mettre tous ces indices dans une liste.
# Comme l'on est en "contexte de chaîne", le filtrage ci-dessous
# va renvoyer la liste des sous-chaînes filtrées par les sous-motifs
# qui correspondent aux expressions parenthésées.
@indice=($string=~m/$er/g);
#-----------------------------------
# 4. on utilise mes indices pour récupérer directement
# les tokens correspondant... en fait on produit
# des sous-tableaux de la longueur du patron et on les imprime
#------------------------------------
my $fin = $#ARGV-1;
for(my $i=0;$i<=$#indice-2;$i=$i+$#ARGV){
my $k=$indice[$i];
my $m=$i+$fin;
my $n=$indice[$m];
# Avec les boucles imbriqués on est obligé d'ouvrir le fichier ici
open(OUT,">>:encoding(iso-8859-1)","./resultat_$sortie.txt");
while ($k <= $n){
print OUT "$listedetokens[$k]\t";
$k++;
}
print OUT "\n";
close(OUT);
}
Variation de la dernière partie du script, avec une procédure à la
place de la boucle while, ceci augmentant la vitesse d'exécution :
#-----------------------------------
# 4. on utilise mes indices pour récupérer directement les tokens
# correspondant... en fait on produit des sous-tableaux de
# la longueur du patron et on les imprime
#------------------------------------
open(OUT,">:encoding(iso-8859-1)","./resultat_$sortie.txt");
my $fin = $#ARGV;
for(my $i=0;$i<=$#indice-2;$i=$i+$fin){
foreach my $k(@indice[&result($i,$fin)]){ print OUT "$listedetokens[$k]\t";
}
print OUT "\n";
}
close(OUT);
# Fin de la procédure principale
#-----------------------------------
# Procédure 'result'
# Renvoi les sous-tableaux de la longueur du patron
sub result{
my $i = shift(@_);
my $fin = shift(@_);
my @listeargument = ();
for(my $n = 0; $n < $fin; $n++){
push(@listeargument,$i+$n);
}
return(@listeargument);
} # Fin de 'result'
Pour télécharger la version "while" du script cliquez ici :
Pour télécharger la version "procédure" du script cliquez ici :
Pour télécharger le fichier obtenu pour N ADJ cliquez ici :
Pour télécharger le fichier obtenu pour N N cliquez ici :
Pour télécharger le fichier obtenu pour N PREP N cliquez ici :
Treetagger
Méthode avec feuille de style XSLT
A
l'issue de l'étape précédente, nous avons obtenu des fichiers XML (un
par rubrique) dont la structure a été conçue de façon à avoir chaque
brève dans une balise "item" et pour chaque "item", deux éléments
"title" et "abstract" correspondant aux titre et résumé.
Les
feuilles de cette arborescence XML sont des éléments "data" de 3 types,
correspondant à la catégorie grammaticale, au lemme et au mot lui-même.
Le
but étant d'extraire des syntagmes correspondant à des patrons
prédéfinis, la feuille de style doit travailler sur les noeuds
"element", père des noeuds "data" ce qui explique la présence de
l'unique règle s'appliquant sur "element".
Les pages HTML ont été générées grâce au logiciel
Oxygen avec les feuilles de styles XSLT.
Pour télécharger la feuille XSLT NOM ADJ cliquez ici :
Pour visualiser la page HTML générée cliquez ici :
Pour télécharger la feuille XSLT NOM NOM cliquez ici :
Pour visualiser la page HTML générée cliquez ici :
Pour télécharger la feuille XSLT NOM PRP NOM cliquez ici :
Pour visualiser la page HTML générée cliquez ici :
Méthode avec XML::XPATH
Nous avons simplement utilisé le script proposé en cours
par Rachid Belmouhoub.
Pour télécharger le fichier obtenu pour NOM ADJ cliquez ici :
Pour télécharger le fichier obtenu pour NOM NOM cliquez ici :
Pour NOM PRP NOM cliquez ici :