<<DOC;
Uyên-To DOAN-RABIER
Ruixin HE
Mohamed Sofiane KERROUA
BàO 2 - Xml::Rss
En utilisant des expressions régulières et le module Xml::Rss, 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_xmlrss.pl nom_du_répertoire
DOC
#/usr/bin/perl
#use strict;
#use warnings;
use Unicode
::String qw(utf8
);
use XML::RSS;
#-----------------------------------------------------------
# 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 $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;
}
}
#-----------------------------------------------------------
# Initialisation de la méthode du module xml::rss
my $rss=new XML::RSS;
eval {$rss->parsefile($file); };
if( $@ ) {
$@ =~ s/at \/.*?$//s; # remove module line number
print STDERR "\nERROR in '$file':\n$@\n";
} else {
#-----------------------------------------------------------
# Détection de la
rubrique avec la méthode du module xml::rss, dans le cas ou il n'y a
pas de rubrique ou classe le fichier dans les non-classés
my $rubrique=$rss->{'channel'}->{'title'};
$rubrique=~ s/Le ?Monde.fr ?://;
$rubrique=~s/ ?- ?Le
?Monde\
.fr
//;
$rubrique=~ s/ //g;
if($rubrique eq ""){
$rubrique = "NONCLASSE";
}
#-----------------------------------------------------------
# Création des fichiers de sortie
open(OUT1
,">>:encoding($encodagesortie)","./resultat/$rubrique.txt");
open(OUT2
,">>:encoding($encodagesortie)","./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>$rubrique</name>\n";
}
if(-z OUT3){
print OUT3
"<?xml version=\"1.0\" encoding=\"$encodagesortie\" ?>\n";
print OUT3
"<name>$rubrique</name>\n";
}
#-----------------------------------------------------------
# Détection de la
date à l'aide des méthodes du module xml::rss, ajout de la date dans
les fichiers de sortie xml
# Ajout de la balise items dans les fichiers de sortie xml
my $date=$rss->{'channel'}->{'pubDate'};
print OUT2
"<date>$date</date>\n";
print OUT3
"<date>$date</date>\n";
#-----------------------------------------------------------
# Détection du titre
et du résumé du fils rss à l'aide des méthodes du module xml::xmlrss
foreach my $item (@{$rss->{'items'}}) {
my $titre=$item->{'title'};
my $resume=$item->{'description'};
#-----------------------------------------------------------
# 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}){
#-----------------------------------------------------------
# Appel de la fonction "nettoietexte" avec comme paramétres le titre et le résumé
$titre=&nettoietexte($titre);
$resume=&nettoietexte($resume);
#-----------------------------------------------------------
# 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 "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"