Boîte à Outil 2

Annotation du texte

Idée principale

Ce deuxième script n’est qu’un enrichissement du 1er script : on ajoute l’écriture du texte annoté par Talismane dans un autre fichier txt et remplace le contenu du xml par le texte annoté par Treetagger.

La plus grande différence entre ces deux outils : Talismane accepte le texte tel quel comme données d’entrée, mais Treetagger ne fonctionne qu’avec liste des mots (phrase segmentée en mots, un mot par ligne). Par conséquent, on utilise un script tokenise-utf8.pl existant pour tokeniser d’abord notre texte. Ensuite, après l’annotation, un autre script treetagger2xml-utf8.pl m’aide à transformer le résultat en format xml.

Attention, j’ai fait un petit changement pour le 2e script. J’organise également ces deux outils. Mon script fonctionne sous une arborescence suivante (elle est téléchargeable dans « bilan des résultats ») :

- Script
- frenchLanguagePack-5.0.4.zip
- treetagger
   -- tokenise-utf8.pl
   -- treetagger2xml-utf8.pl (modifié)
- Talismane

Savoir plus sur TreeTagger et Talismane.

Ici, on utilise différemment ces deux annotateurs. Pour TreeTagger, on transmet chaque fois un seul titre ou description pour l’annotation ; mais pour Talismane, on concatène d’abord tous les titres et les descriptions d’un fils RSS et puis on envoie cet ensemble à l’annotateur. C’est évident que le 2e moyen est plus efficace. D’ailleurs, ce script prend en total environ 5 heures pour finir le travail.

Finalement, voici mon script de boîte à outils 2 et des exemples de résultat de la rubrique « Tecnologies » (651865) (Vous pouvez trouver d’autres dans la section « conclusion et résultat ».) :

Script et résultat

#usr/bin/perl -w
<<DOC; 
Votre Nom : Jianying LIU
JANVIER 2020
 usage : perl BaO2.pl repertoire-a-parcourir rubrique
 Le programme prend en entrée le nom du répertoire-racine contenant les fichiers
 à traiter et le nom de la rubrique à traiter parmi ces fichiers
DOC
use strict;
use utf8;

#indiquer l'encodage de sortie dans le console
binmode(STDOUT, ":utf8");

my $rep = $ARGV[0];       #?guillemets?
$rep =~ s/[\/]$//;          #[\/] choisir entre deux
my $rubrique = $ARGV[1];

#-------------------
#programme principal
#-------------------
#ouvrir le fichier txt et le fichier xml pour l'écriture
open(TXT, ">:encoding(utf8)", "sortie_$rubrique.txt");
open(XML, ">:encoding(utf8)", "sortieTreetagger_$rubrique.xml");
open(TALISMANE, ">:encoding(utf8)", "sortieTalismane_$rubrique.txt");
print XML "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<corpus2019>\n";    #écrire la tête du fichier xml

my $i = 1;      #compteur pour le calcul total de fichiers rss traités
my $count_item = 1;
my %dico_titres = ();
&parcoursArbFic($rep);

print XML "</corpus2019>\n";
close TXT;
close XML;
close TALISMANE;
unlink qw(bao2_talis.tal boa2_talis.txt temporaire.txt test.txt.pos test.txt.pos.xml);   #supprimer les fichiers temporaires
exit;


###############################################

sub parcoursArbFic {
	my $path = shift(@_);    #shift obligatoire
	my @files = <$path/*>;  #cette opération renvoie la liste des fichiers/répertoire dans ce répertoire, sans . et .. (donc pas besoin de tester et sauter), ordonné, avec chemin complet (donc pas besoin de concaténation pour obtenir le path
	foreach my $file (@files) {
		#if rep. recursif
		if (-d $file) {
			&parcoursArbFic($file);
		}
		#if file : open, chercher motif, ecrire   sous-fonction
		if (-f $file and $file =~ /$rubrique.+xml$/) {
			print $i++," Traitement de : ",$file,"\n";
			&ecritureFic($file);
		}
	}	
}

#traitement sur un fichier rss cherché
sub ecritureFic{
	#ouvrir le fichier RSS
	my $fichier = shift(@_);
	open(RSS, "<:encoding(utf8)", $fichier);
	#lecture global du fichier
	$/ = undef;
	my $textelu = <RSS>;
	close RSS;
	
	#Talismane : pour chaque rss : regrouper tous les item et puis annoter; donc ici initialiser le texte global
	my $titre_description_global = "";
	
	#chercher motif avec RegExp
	while ($textelu =~ /<item>.*?<title>(.+?)<\/title>.+?<description>(.+?)<\/description>/sg){  #m multiple lines, on peut matcher plusieurs lignes,influencer ^ et $; s influence . qui peut matcher aussi \n maintenant
		my $titre = $1;
		my $description = $2;
		#tester si ce titre existe déjà dans le dico_titre
		if (! (exists $dico_titres{$titre})){   #!布尔值取反 存在 --> 不存在; exists fonctionne sur les clés
			$dico_titres{$titre} = $description;
			($titre, $description) = &nettoyage($titre,$description);  #sans paranthèses, on n'arrive pas à ajouter le point à la fin de chaque titre, mais pourquoi??
			$titre_description_global = $titre_description_global.$titre."\n".$description."§\n";
			my $titre_etiket = &etiquetage($titre);
			$titre_etiket =~ s/\r//g;
			my $description_etiket = &etiquetage($description);
			$description_etiket =~ s/\r//g;
			#écrire le contenu dans deux fichiers
			print TXT "$titre\n$description\n--------------------\n";
			print XML "<item numero=\"$count_item\">\n<titre>$titre_etiket<\/titre>\n<description>$description_etiket<\/description>\n<\/item>\n";   #slash可以转义也可不转
			$count_item++;
		}
	}
	#lancer Talismane et ecrire le fichier txt de Talismane
	my $texte_annote_talis = &etiquetageTal($titre_description_global);
	print TALISMANE $texte_annote_talis;
}


#nettoyer le contenu extrait du rss avec une sous-fonction
sub nettoyage {
	my $titre = $_[0];
	my $description = $_[1];
	$titre=~s/^<!\[CDATA\[//; ##
	$titre=~s/\]\]>$//;       ##
	$description=~s/^<!\[CDATA\[//;  ##
	$description=~s/\]\]>$//;  ##
	$description=~s/&lt;.+?&gt;//g;
    $description=~s/&#38;#39;/'/g;
    $description=~s/&#38;#34;/"/g;
	$description=~s/ +/ /g;   #supprimer les espaces abondantes successifs; le nettoyage manquant?
    $titre=~s/&lt;.+?&gt;//g;
    $titre=~s/&#38;#39;/'/g;
    $titre=~s/&#38;#34;/"/g;
    $titre=~s/([^?\.])$/$1\./g;         #?ajouter un point à la fin de chaque titre####
    return $titre,$description;
}

#etiquetage par treeTagger
sub etiquetage {
	my $texte = $_[0];
	open (ETI, ">:encoding(utf8)", "temporaire.txt");
    print ETI $texte;
    close ETI;
    `perl -f ./treetagger/tokenise-utf8.pl temporaire.txt | ./treetagger/tree-tagger.exe ./treetagger/french-oral-utf-8.par -token -lemma -no-unknown > test.txt.pos`;
    `perl ./treetagger/treetagger2xml-utf8.pl test.txt.pos utf8`; #résultats dans test.txt.pos.xml
    open (TEMP, "<:encoding(utf8)", "test.txt.pos.xml");
    $/=undef;
    my $texte_annote_xml=<TEMP>;
    close TEMP;
    $texte_annote_xml=~s/^<\?xml[^>]+>//;
	return $texte_annote_xml;
}

#etiquetage par Talismane
sub etiquetageTal {
	my $texte_global = $_[0];
	open(TALIS, ">:encoding(utf8)","boa2_talis.txt");
	print TALIS $texte_global;
	close TALIS;
	
	`java -Xmx1G -Dconfig.file=./Talismane/talismane-fr-5.0.4.conf -jar ./Talismane/talismane-core-5.1.2.jar --analyse --sessionId=fr --encoding=UTF8 --inFile=boa2_talis.txt --outFile=bao2_talis.tal`;
	
	open(TEMP, "<:encoding(utf8)", "bao2_talis.tal");
    my $temp=<TEMP>;
    close TEMP;
	return $temp;
}

boîte à outils 1

Parcours du répertoire arborescent, extraction du texte

Savoir plus

boîte à outils 3

Récupération des patrons morphosyntaxiques

Savoir plus