Boîte à outils 1

 

 

Le rôle de cette boîte à outils est de parcourir l'arborescence des fichiers XML contenant les flux RSS pour en extraire les champs "titre" et "description". Ainsi, notre objectif est de produire deux types de fichiers de sorties par rubrique (culture, internationale, sport, etc.): un fichier au format ".txt" et un autre au format XML contenant chacun les titres et les descriptions des mises à jour à partir du corpus 2014.

 

Les fichiers contenant les flux RSS sont organisés dans des sous-répertoires d'un répertoire principal. Ce dernier est parcouru récursivement (la fonction "parcoursarborescencefichiers" appelle elle même à la rencontre de chaque sous-répertoire):

 

sub parcoursarborescencefichiers 
{
    my $path = shift(@_);
    opendir(DIR, $path) or die "Can't open $path: $!\n";
    my @files = readdir(DIR);
    closedir(DIR);
    foreach my $file (@files) 
    {
        next if $file =~ /^\./;
        $file = $path."/".$file;
        if (-d $file) 
        {
            &parcoursarborescencefichiers($file);   
        }
        if (-f $file)
        {

 

A la rencontre d'un fichier, le programme teste si celui-ci est au format XML et son nom ne commence pas par le motif "fil":

 

if (-f $file)
{
    if (($file=~/\.xml$/) && ($file!~/\/fil.+\.xml$/))
    {
        # Récupérer l'encodage du fichier

 

Par la suite, l'appel de la fonction "trouve_encodage" pour le fichier courant permet de récupérer l'encodage du fichier XML du flux RSS:

 

# Récupérer l'encodage du fichier
my $encodage=trouve_encodage($file);
# si l'encodage n'est pas vide, faire le traitement...
if ($encodage ne "")
{
    my $texte = "";
    my $texteXML="<file>\n";
    $texteXML.="<name>$file</name>";
    $texteXML.="<items>\n";
    my $texteBRUT="";
    # Trouver la rubrique

 

Enfin, si l'encodage est trouvé, on appelle la fonction "trouve_rubrique" qui va rouvrir le fichier XML avec le bon encodage afin de chercher la rubrique du flux RSS contenu dans ce fichier:

 

# Trouver la rubrique
my ($rub, $texte) = trouve_rubrique($file, $encodage);
print "RUBRIQUE : $rub\n";

 

Voici maintenant la fonction repererubriques qui exécute toutes les étapes citées ci-dessus et sauvegarde l'ensemble des rubriques dans "$dicoRUB":

 

sub repererubriques {
    my $path = shift(@_);
    opendir(DIR, $path) or die "can't open $path: $!\n";
    my @files = readdir(DIR);
    closedir(DIR);
    foreach my $file (@files) {
        # Ignorer les répertoire . et .. et tous les fichiers cachés (commençant par .)
        next if $file =~ /^\./;
        # Construire le nom de fichier en lui rajoutant le chemin complet
        $file = $path."/".$file;
        if (-d $file) {
            &repererubriques($file);    
        }
        if (-f $file) {
            # Ne traiter que les fichiers "xml" (ignorer aussi les fichiers ayant le format "filXXX.xml")
            if (($file=~/\.xml$/) && ($file!~/\/fil.+\.xml$/)) {
                # Récupérer l'encodage du fichier
                my $encodage = trouve_encodage($file);
                if ($encodage ne "") {
                    # Trouver la rubrique
                    my ($rub, $texte) = trouve_rubrique($file, $encodage);
                    # mémoriser les rubriques
                    if ($rub ne ""){
                        $dicoRUB{$rub}++;
                    }
                }
                else {
                    print"Fichier $file ==> encodage non détecté \n";
                }
            }
        }
    }
}

 

On passe ensuite à la détection des titres et descriptions, que l'on stocke dans des variables pour effectuer plusieurs traitements :

 

while ($texte =~ /<item><title>(.+?)<\/title>.+?<description>(.+?)<\/description>/g) 
{
    my $titre=$1;
    my $desc=$2;
    ###############################
    my $rss = new XML::RSS;
    $rss->parsefile($file);
    foreach my $item(@{$rss->{'items'}})
    {
        my $titre = $item->{'title'};
        my $desc = $item->{'description'};

        # si l'encodage n'est pas UTF-8, réencoder via le module Unicode::String
        if (uc($encodage) ne "UTF-8"){
            utf8($titre);
            utf8($desc);
        }
        # traiter les caractère diachrités avec HTML::Entities
        $titre = HTML::Entities::decode($titre);
        $desc = HTML::Entities::decode($desc);
        $titre = &clean($titre);
        $desc = &clean($desc);
        # verifier s'il n'y a pas de doublons
        while ($texte =~ /<item><title>(.+?)<\/title>.+?<description>(.+?)<\/description>/g) 
        {
            my $titre=$1;
            my $desc=$2;
            ###########################
            my $rss = new XML::RSS;
            $rss->parsefile($file);
            foreach my $item(@{$rss->{'items'}})
            {
                my $titre = $item->{'title'};
                my $desc = $item->{'description'};

                # si l'encodage n'est pas UTF-8,réencoder via le module Unicode::String
                if (uc($encodage) ne "UTF-8"){
                    utf8($titre);
                    utf8($desc);
                }
                # traiter les caractère diachrités avec HTML::Entities
                $titre = HTML::Entities::decode($titre);
                $desc = HTML::Entities::decode($desc);
                $titre = &clean($titre);
                $desc = &clean($desc);
                # verifier s'il n'y a pas de doublons

 

La fonction "clean" permet de supprimer les balises non pertinentes intégrées aux titres et descriptions et de filtrer certains caractères indésirables.

 

sub clean {
    my $texte=shift;
    $texte=~s/<img[^>]+>//g;
    $texte=~s/<a href[^>]+>//g;
    $texte=~s/<\/a>//g;
    $texte=~s/<[^>]+>//g;
    $texte=~s/&/et/g;
    $texte=~s/\x{201c}/“/g;
    $texte=~s/\x{201d}/”/g;
    $texte=~s/\x{2019}/’/g;
    $texte=~s/\x{2018}/‘/g;
    $texte=~s/\x{2013}/-/g;
    $texte=~s/\x{2192}/→/g;
    $texte=~s/\x{2026}/.../g;
    $texte=~s/\x{0153}/œ/g; 
    $texte=~s/\x{0152}/Œ/g;
    $texte=~s/\x{fffd}/�/g; # caractère de remplacement
    $texte=~s/\x{20ac}/€/g;
    $texte=~s/\x{2009}/ /g; # thin space
    return $texte;
}

 

Les titres et les discriptions ne doivent pas être stockés en doublons. Pour cela, on utilise des tables de hashage (dictionnaires):

 

my %dicoTITRES=();
my %dicoDESC=();
my %dicoRUB=();

 

if (!(exists $dicoTITRES{$titre}) and (!(exists $dicoDESC{$desc}))){     
    $dicoTITRES{$titre}++;
    $dicoDESC{$desc}++;
    $texteXML.="<item>\n<title>$titre</title>\n<description>$desc</description>\n</item>\n";  
    print OUTTXT "$titre\n";
    print OUTTXT "$desc\n";

 

L'intérêt que nous portons à l'encodage est que nous voulons que les sorties XML soient en UTF-8 et les sorties ".txt" en ISO-8859-1.

 

my $output1=$sortie.$rub.".xml";
my $output2=$sortie.$rub.".txt";
if (!open (OUTXML,">>:encoding(utf-8)", $output1)) 
{
    die "Can't open file $output1";
}
if (!open (OUTTXT,">>:encoding(iso-8859-1)", $output2)) 
{
    die "Can't open file $output2";
}

 

Vous pouvez télécharger ici le script entier

Vous pouvez également voir ici un exemple du résultat TXT et XML pour la rubrique CINEMA.

 

Nous pouvons désromais passer à à la boîte à outils 2 où on va utiliser des outils d'annotation afin d'étiqueter les titres et les descriptions.