<<DOC;
Uyên-To DOAN-RABIER
Ruixin HE
Mohamed Sofiane KERROUA

BàO 2 - Xml::Rss

En utilisant des expression régulière 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"
mkdir(resultat); 
#Les fichiers pour cordial sont crées dans un répertoire "cordial"
mkdir(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";
my @files = readdir(DIRS);
closedir(DIRS);
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");
				print OUT "</file>\n";
				close(OUT);
			}
			# 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>){
		 print OUT4 $_; 
	}
		close (OUT4);
		close (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";
my @fics = readdir(COR);
closedir(COR);
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
}

exit; # Fin du programme

#-----------------------------------------------------------
# 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
    my $path = shift(@_);
    opendir(DIR, $path) or die "can't open $path: $!\n";
    my @files = readdir(DIR);
    closedir(DIR);

#-----------------------------------------------------------
# Traitement de chaque fichier 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
				open(FIC,$file);
				while (my $ligne=<FIC>) {
					$ligne =~ s/\n//g;
					if($ligne =~/(iso-8859-1|utf-8)/ig){
						$encodage = $1;
					}
				}
				close(FIC);
				
#-----------------------------------------------------------
# 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/é/e/gi;
					$rubrique=~s/è/e/gi;
					$rubrique=~s/ê/e/gi;
					$rubrique=~s/à/a/gi;
					$rubrique=~ s/Le ?Monde.fr ?://;
					$rubrique=~s/ ?- ?Le ?Monde\.fr//;
					$rubrique=~s/es$/e/i;
					$rubrique=~ s/ //g;
					$rubrique=uc($rubrique);
					
					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 "<file>\n";
						print OUT2 "<name>$rubrique</name>\n";
					}
					
					if(-z OUT3){	
				    print OUT3 "<?xml version=\"1.0\" encoding=\"$encodagesortie\" ?>\n";
				    print OUT3 "<file>\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 OUT2 "<items>\n";
					print OUT3 "<date>$date</date>\n";
					print OUT3 "<items>\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
					print OUT2 "</items>\n";
					print OUT3 "</items>\n";
					close(OUT1);
					close(OUT2);
					close(OUT3);
					}
				}
			}
		}
	}
} # 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";
    close(TMPFILE);
    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;
    }
    close(OUT);
    #----- le resume
    open (TMPFILE,">:encoding(utf-8)", $tmptag);
    print TMPFILE $texte,"\n";
    close(TMPFILE);
    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;
    }
    close(OUT);
    # 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 {
    my $texte=shift;
    $texte =~ s/&lt;/</g;
    $texte =~ s/&gt;/>/g;
    $texte =~ s/<a href[^>]+>//g;
    $texte =~ s/<img[^>]+>//g;
    $texte =~ s/<\/a>//g;
    $texte =~ s/&#38;#39;/'/g;
    $texte =~ s/&#38;#34;/"/g;
    $texte =~ s/&#233;/é/g;
    $texte =~ s/&#234;/ê/g;
    $texte =~ s/<[^>]+>//g;
    $texte =~ s/&nbsp;/ /g;
    $texte=~s/&#39;/'/g;
    $texte=~s/&#34;/"/g;
    $texte=~s/&amp;#39;/'/g;
    $texte=~s/&amp;#34;/"/g;
    return $texte;
} # 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{
my $fichier = shift(@_);
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");
	print OUT $ligne;
	$taille = -s OUT;
	close(OUT);
	}else{
     $num++;
	 $taille = 0;
	}
}
close (F);
} # Fin "decoupage"
