<<DOC;
Uyên-To DOAN-RABIER
Ruixin HE
Mohamed Sofiane KERROUA
BàO 2 - Expression régulière
En utilisant uniquement des expressions régulières, produit en sortie des fichiers contenant les résumés de fils rss
contenus dans des fichiers xml dans une arborescence donnée. Produit en plus des fichiers étiquetés par tree-tagger et
des fichiers exploitables par Cordial (>2Mo et en iso-8859-1).
usage : bao2_regexp.pl nom_du_répertoire
DOC
#/usr/bin/perl
#use strict;
#use warnings;
use Unicode
::String qw(utf8
);
#-----------------------------------------------------------
# Procédure principale
#-----------------------------------------------------------
#Les fichiers sont créés dans un répertoire "resultat"
#Les fichiers pour cordial sont créés dans un répertoire "cordial"
mkdir("./cordial/fichiers");
#-----------------------------------------------------------
# on initialise une variable $rep contenant le flux de sortie
my $rep="$ARGV[0]";
# on s'assure que le nom du répertoire ne se termine pas par un "/"
$rep=~ s/[\/]$//;
#-----------------------------------------------------------
# Initialisation d'un tableau de hash évitant la répétition du contenu des fils rss
my %tabcontenu = ();
&parcoursarborescencefichiers($rep); #recurse!
#-----------------------------------------------------------
$cheminrep ="./resultat";
# On ouvre le répertoire "résultat" contenant les fichiers de sortie xml et txt
# On ajoute à chaque fichier xml la balise fermante </file>
# On convertit chaque fichier txt en iso-8859-1 et on le place dans le dossier cordial
opendir(DIRS
,$cheminrep) or die "can't open $cheminrep: $!\n";
foreach my $fichier(@files){
next if $fichier =~ /^\.\.?$/;
# A chaque fichier xml crée en sortie on ajoute la balise fermante </file>
if($fichier =~/\.xml$/){
open(OUT
,">>:encoding(utf-8)","./resultat/$fichier");
}
# Chaque fichier txt est converti en iso-8859-1 pour un traitement avec Cordial
if($fichier=~/\.txt$/){
open(IN
,"<:encoding(utf8)","./resultat/$fichier");
open (OUT4
, ">:encoding(iso-8859-1)","./cordial/iso_$fichier");
while(<IN>){
}
}
}
#-----------------------------------------------------------
# Ouverture du répertoire cordial afin de découper les fichiers de plus de 2Mo pour les traiter avec Cordial
$cordial="./cordial";
opendir(COR
, $cordial) or die "can't open $path: $!\n";
foreach my $fich(@fics){
next if $fich =~ /^\.\.?$/;
&decoupe($fich); # Procédure qui permet de couper un fichier de plus de 2Mo en plusieurs fichiers de 2Mo maximum
}
#-----------------------------------------------------------
# Procédure "parcoursarborescencefichiers"
# Parcours une arborescence et traite chaque fichier xml contenant des fils rss
# Donnée : un répértoire passé en paramètre par valeur
# Résultats : - le résultat du traitement au format txt
# - le résultat du traitement au format xml
# - le résultat du traitement au format xml avec un étiquetage réalisé tree-tagger
sub parcoursarborescencefichiers {
#-----------------------------------------------------------
# Récupération du répertoire et ouverture du répertoire
opendir(DIR
, $path) or die "can't open $path: $!\n";
#-----------------------------------------------------------
# Traitement de chaques fichiers contenu dans le répertoire
foreach my $file (@files) {
next if $file =~ /^\.\.?$/;
$file = $path."/".$file;
# Si on tombe sur un répertoire on relance la procédure
if (-d $file) {
&parcoursarborescencefichiers($file); #recurse!
}
#-----------------------------------------------------------
# Traitement du fichier
if (-f $file) {
# Si le fichier est un fichier xml et si ce fichier xml n'est pas un fichier ne contenant pas fils rss on le traite
if(($file=~/\.xml$/) && ($file!~/\/fil.+\.xml$/) && ($file !~/0,2-3404,1-0,0\.xml$/)) {
# Initialisation des différentes variables
my $rubrique="";
my $encodage = "";
my $encodagesortie="utf-8";
my $texte="";
#-----------------------------------------------------------
# Si le fichier est vide pas de traitement
if (-z $file) {
print "$file est vide: pas de traitement\n";
}else{
#-----------------------------------------------------------
# Détection de l'encodage du fichier
while (my $ligne=<FIC>) {
$ligne =~ s/\n//g;
if($ligne =~/(iso-8859-1|utf-8)/ig){
$encodage = $1;
}
}
#-----------------------------------------------------------
# Détection de la
rubrique en mettant le texte sur une ligne, dans le cas ou il n'y a pas
de rubrique ou classe le fichier dans les non-classés
open(FILE
,"<:encoding($encodage)",$file);
while (my $ligne=<FILE>){
$ligne =~ s/\n//g;
$texte .= $ligne;
}
if ($texte=~/<channel><title>([^<]+)<\/title>/){
$rubrique = $1;
$rubrique=~ s/Le ?Monde.fr ?://;
$rubrique=~ s/ ?- ?Le ?Monde.fr//;
$rubrique=~ s/es$/e/i;
$rubrique=~ s/ //g;
}
if($rubrique eq ""){
$rubrique = "non-classe";
}
#-----------------------------------------------------------
# Création des fichiers de sortie
open(OUT1
,">>:encoding(utf-8)","./resultat/$rubrique.txt");
open(OUT2
,">>:encoding(utf-8)","./resultat/$rubrique.xml");
open(OUT3
,">>:encoding(utf-8)","./resultat/$rubrique-treetagger.xml");
#-----------------------------------------------------------
# Ajout des entêtes dans les fichiers de sortie xml
if(-z OUT2){
print OUT2
"<?xml version=\"1.0\" encoding=\"$encodagesortie\" ?>\n";
print OUT2
"<name>$ARGV[0]</name>\n";
}
if(-z OUT3){
print OUT3
"<?xml version=\"1.0\" encoding=\"$encodagesortie\" ?>\n";
print OUT3
"<name>$ARGV[0]</name>\n";
}
#-----------------------------------------------------------
# Suppression des
espaces inutiles, détection de la date du fichier
$texte =~ s/> *</></g;
$texte=~/<pubDate>([^<]+)<\/pubDate>/;
my $date=$1;
#-----------------------------------------------------------
# Conversion de la date en utf-8 si l'encodage du fichier en entrée ne l'est pas
if (uc($encodage) ne "UTF-8") {utf8
($date);}
#-----------------------------------------------------------
# Ajout de la date et de la balise ouvrante items dans les fichier de sortie xml
print OUT2
"<date>".$date."</date>\n";
print OUT3
"<date>".$date."</date>\n";
#-----------------------------------------------------------
# Détection du titre et du résumé du fils rss
while ($texte =~ /<item><title>(.+?)<\/title>.+?<description>(.+?)<\/description>/g) {
my $titre=$1;
my $resume=$2;
#-----------------------------------------------------------
# Test sur le titre du fil rss, si il est déjà contenu dans le tableau de hash on ne le traite pas
my $test = $titre;
if(!exists $tabcontenu{$test}){
#-----------------------------------------------------------
# Conversion du titre et du résumé en utf-8 si l'encodage du fichier en entrée ne l'est pas
if (uc($encodage) ne "UTF-8") {utf8
($titre);utf8
($resume);}
#-----------------------------------------------------------
# Appel de la fonction "nettoietexte" avec comme paramétres le titre et le résumé
$titre = &nettoietexte($titre);
$resume = &nettoietexte($resume);
#-----------------------------------------------------------
# Appel de la fonction "etiquetage" avec comme paramétres le titre et le résumé
my ($titreetiquete, $resumeetiquete) = &etiquetage ($titre, $resume);
#-----------------------------------------------------------
# On ajoute dans les différents fichiers le titre et le résumé
print OUT1
"Titre : $titre \n";
print OUT1
"Resume : $resume \n";
print OUT2
"<item><title>$titre</title><abstract>$resume</abstract></item>\n";
print OUT3
"<item>\n<title>\n$titreetiquete</title>\n<abstract>\n$resumeetiquete</abstract>\n</item>\n";
#-----------------------------------------------------------
# On ajoute dans le tableau de hash le titre du fil rss
$tabcontenu{$test}++;
}
}
#-----------------------------------------------------------
# Fermeture de la balise items dans les fichiers xml, fermeture des fichiers
}
}
}
}
} # Fin "parcoursarborescencefichiers"
#-----------------------------------------------------------
# Fonction "etiquetage"
# Permet d'etiqueter un texte avec le programme extérieur tree-tagger
# Données : - $titre : une variable contenant des chaînes de caractères en utf-8
# - $resume : : une variable contenant des chaînes de caractères en utf-8
# Résultats : 2 variables contenant le texte étiqueté par tree-tagger
sub etiquetage {
my ($titre,$texte)=@_;
#----- le titre
my $codage="utf-8";
my $tmptag="texteaetiqueter.txt";
open (TMPFILE
,">:encoding(utf-8)", $tmptag);
print TMPFILE
$titre,"\n";
system("perl
./treetagger-win32/cmd/tokenise-fr.pl $tmptag | tree-tagger.exe
./treetagger-win32/lib/french-utf8.par -lemma -token -no-unknown -sgml
> treetagger.txt");
system("perl ./treetagger-win32/cmd/treetagger2xml-utf8.pl treetagger.txt $codage ");
# lecture du resultat tagge en xml :
open(OUT
,"<:encoding(utf-8)","treetagger.txt.xml");
my $fistline=<OUT>;
my $titreetiquete="";
while (my $l=<OUT>) {
$titreetiquete.=$l;
}
#----- le resume
open (TMPFILE
,">:encoding(utf-8)", $tmptag);
print TMPFILE
$texte,"\n";
system("perl
./treetagger-win32/cmd/tokenise-fr.pl $tmptag | tree-tagger.exe
./treetagger-win32/lib/french-utf8.par -lemma -token -no-unknown -sgml
> treetagger.txt");
system("perl ./treetagger-win32/cmd/treetagger2xml-utf8.pl treetagger.txt $codage");
# lecture du resultat tagge en xml :
open(OUT
,"<:encoding(utf-8)","treetagger.txt.xml");
my $fistline=<OUT>;
my $texteetiquete="";
while (my $l=<OUT>) {
$texteetiquete.=$l;
}
# on renvoie les resultats :
return ($titreetiquete,$texteetiquete);
} # Fin "etiquetage"
#-----------------------------------------------------------
# Fonction "nettoietexte"
# Nettoie un texte de ses entités xml
# Donnée : une chaîne de caractère contenant des entités xml
# Résultat : la chaîne de caractères nettoyée de ses entités xml
sub nettoietexte {
$texte =~ s/</</g;
$texte =~ s/>/>/g;
$texte =~ s/<a href[^>]+>//g;
$texte =~ s/<img[^>]+>//g;
$texte =~ s/<\/a>//g;
$texte =~ s/&#39;/'/g;
$texte =~ s/&#34;/"/g;
$texte =~ s/é/é/g;
$texte =~ s/ê/ê/g;
$texte =~ s/<[^>]+>//g;
$texte =~ s/ / /g;
} # Fin "nettoietexte"
#-----------------------------------------------------------
# Procédure "decoupe"
# Decoupe des fichiers de plus de 2Mo en plusieurs fichiers de 2Mo
# Donnée : une variable contenant le nom d'un fichier à couper
# Résultat : les fichiers découpés crées dans un répertoire "fichiers" contenu dans le répertoire "cordial"
sub decoupe{
open(F
,"./cordial/$fichier");
my $num = 1;
my $taille = 0;
while($ligne = <F>) {
if($taille < 2000000){ # On veut des fichiers de 2Mo = 2000000 octets
open (OUT
,">>./cordial/fichiers/$fichier".$num.".txt");
}else{
$num++;
$taille = 0;
}
}
} # Fin "decoupage"