Automatisar um processo de coleta e análise de padrões lexicais de um corpus texto.
Criar vários script em Perl que possam ser modificidos e adaptados para trabalhar com diversos contextos diferentes, mas com objetivos similares.
Exibir os resultados em forma de gráficos acompanhados de nossa interpretação.
Os dados são compostos de feeds RSS de 2014 do jornal Le Monde. Os arquivos encontram-se em formato XML e organizados em pastas separadas por mês de publicação.
Nosso primeiro script percorre a estrutura de arquivos e extrai todo conteúdo presente nas balisas <title> e <description>. Esses dados são em seguida tratados para que seja feita a substituição des caractères especiais, a exclusão das imagens e de outros dados que não serão tratados.
Esta ferramenta coleta a saída do script 1 e utilisa dos etiquetadores de parte do discurso (POS Tagger) diferentes: TreeTagger e Cordial.
A ferramenta 3 é composta de dois scripts diferentes; um para tratar a saída feita por TreeTagger e outro para tratar a saída Cordial. O objetivo é buscar padrões morfosintáticos específicos nesses dois resultados (ex. substantivo-preposição-substantivo)
Nossa última ferramenta utiliza as sequência encontradas para criar um representação visual desses syntagmas dentro do texto.
Nós somos estudantes do primeiro ano de mestrado du curso Tratamento Automático de Línguas Naturais oferecido pelo Institut National des Langues et Civilisations Orientales (INALCO) em Paris, França. Mais informações sobre a nossa formação podem ser encontradas neste link (textos em Francês).
Que fait l'outil 1 ?
O projeto Caixa de Ferramentas 1 é composto por um programa que lê a estrutura dos feeds RSS do jornal Le Monde. Os arquivos estão organizados em uma pasta nomeada 2014 (o ano no qual nos realizamos a pesquisa). Esta pasta contém subpastas, um para cada mês, dentros das quais estão estocadso arquivos XML e TXT, contendo os artigos e as tags. Todo esse material encontra-se organizado par tema (Política, Cultura, etc.). Para o nosso projeto, nós utilizamos somente os arquivos XML.
Exemplo de um arquivo XML utilizado no projeto:
Nosso programa extrai todo conteúdo presente entre as tag <title> e <description> de cada arquivo XML. Como existe a possibilidade de haver feeds RSS repetidos é importante se assegurar que cada arquivo será tratado somente uma única vez. Os dados são em seguida tratados para realizar a substituição dos caracteres especiais e a exclusão das imagens e outros dados que não são tratados pelo programa.
Exemplo das tags <title> e <description> para verificar qual o tipo de limpeza devemos efetuar:
Duas saídas são produzidas: Uma no formato TXT e outra no formato XML. O Formato TXT contém descrições antes de cada título (ex. Title: L'Unedic a versé 756 millions d'euros d'allocations chômage à tort en 2013 § Description:L'Unedic, qui gère les allocations chômage, estime que « le poids des indus rapportés aux dépenses d'indemnisation est resté stable, à 2,52 % ». §) e formato XML mantém as tags <title> e <description>.
Saída da Ferramenta 1
Ao escrever nosso programa nós tivemos que contornar alguns problemas. O primeiro deles foi a diferença de codificação dos caracteres. Os arquivos não possuem codificações diferentes. Nós podemos encontrar arquivos codificados em iso-8859-x ou utf-8, por exemplo. Porém, nós queríamos que todos as saídas de resultado estivessem codificados em utf-8. Um outro problema diz respeito à formatação dos arquivos, pois alguns deles contêm tag em linha diferentes e outros na mesma linha. Como nós não queríamos ter escrever dois script diferentes para cada caso, nós tivemos então que encontrar um meio para tratá-los com um único script.
A realização correta desta etapa foi muito importante, pois os resultados produzidos pela Caixa de Ferramentas 1 são reutilizados pelas CdF 2, CdF 3 e CdF 4. Deixar tags HTML nos arquivos, por exemplo, poderia ter uma consequência grave no momento de realizar a etiquetagem das partes do discurso.
Perl
Vocês irão perceber que nossos programas são classificados de duas distintas: "Puro Perl" e "Módulos Perl". Nos dois casos, nós utilizamos a linguagem Perl (v5.xx.x), porém nos programas que nós chamamos "Perl Puro" nós utilizamos uma abordagem direta. Isto quer dizer que todas as etapas realizadas no tratamento dos dados são visíveis no programa e não há nenhum programa externo em Perl (módulos) que poderiam introduzir variáveis externas não declaradas capazes de desestabilizar o programa. Neste caso, nós utilzamos expressões regulares (regex) para encontrar as informações que nós gostaríamos de extrair.
Este script utilizar uma abordagem "Perl puro". Para executar o script, é necessário utilizar o comando "perl nome_do_progama.p pasta_de_arquivos" no terminal. Este programa cria duas saídas(TXT e XML, linhas 23-26) e lê o caminho do arquivo para encontrar os arquivos corretos com auxílio de uma função recursiva (linha 28, função linha 40-95). Esta função chama a função responsável pela limpeza do texto (linhas 65 e 78)
e verifica também se nós não tratamos várias vez o mesmo texto, utilizando um hash para armazenar apenas uma cópia de cada texto. Nós incluímos também as tags XML no arquivo de saída. Por fim, nós escrevemos os resultados nos dois arquivos (linhas 33 e 36).
- #/usr/bin/perl
- <<DOC;
- Seu nome :
- JANVIER 2015
- utilização : perl parcours-arborescence-fichiers repertoire-a-parcourir
- O programa recebe como argumento de entrada o nome da pasta contendo os arquivos a serem tratados
- O programa constrói na saída um arquivo estruturado contendo em cada linha
- o nome do arquivo e o resultado da filtragem :
- <FICHIER><NOM>du fichier</NOM></FICHIER><CONTENU>du filtrage</CONTENU></FICHIER>
- DOC
- #-----------------------------------------------------------
- my $rep="$ARGV[0]";
- # on s'assure que le nom du répertoire ne se termine pas par un "/"
- $rep=~ s/[\/]$//;
- # on initialise une variable contenant le flux de sortie
- my $DUMPFULL1="";
- my $DUMPFULL2="";
- my $cptArticle=0;
- my %dicoDesTitres=();
- my %dicoDesDescriptions=();
- #----------------------------------------
- my $output1="SORTIE.txt";
- if (!open (FILEOUTTXT,">$output1")) { die "Pb a l'ouverture du fichier $output1"};
- my $output2="SORTIE.xml";
- if (!open (FILEOUTXML,">$output2")) { die "Pb a l'ouverture du fichier $output2"};
- #----------------------------------------
- &parcoursarborescencefichiers($rep); #recurse!
- #----------------------------------------
- print FILEOUTXML "<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?>\n";
- print FILEOUTXML "<PARCOURS>\n";
- print FILEOUTXML "<NOM>SF</NOM>\n";
- print FILEOUTXML "<FILTRAGE>".$DUMPFULL1."</FILTRAGE>\n";
- print FILEOUTXML "</PARCOURS>\n";
- close(FILEOUTXML);
- print FILEOUTTXT $DUMPFULL2;
- close(FILEOUTTXT);
- exit;
- #----------------------------------------------
- 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); #recurse!
- }
- if (-f $file) {
- if ($file=~/\.xml$/) {
- print $i++,"\n";
- open(FILEIN,$file);
- while (my $ligne=<FILEIN>) {
- if ($ligne=~/<\/item>/) {
- $DUMPFULL1.="</article>\n";
- }
- if ($ligne=~/<item>/) {
- $cptArticle++;
- $DUMPFULL1.="<article numero=\"$cptArticle\">\n";
- }
- if ($ligne=~/<description>(.+?)<\/description>/) {
- my $text=$1;
- $text=&nettoieText($text);
- if (!(exists($dicoDesDescriptions{$text}))) {
- $DUMPFULL1.="<description>$text</description>\n";
- $DUMPFULL2.=$text."\n";
- $dicoDesDescriptions{$text}++;
- }
- else {
- $dicoDesDescriptions{$text}++;
- $DUMPFULL1.="<description>-</description>\n";
- }
- }
- if ($ligne=~/<title>(.+?)<\/title>/) {
- my $text=$1;
- $text=&nettoieText($text);
- if (!(exists($dicoDesTitres{$text}))) {
- $DUMPFULL1.="<abstract>$text</abstract>\n";
- $DUMPFULL2.=$text."\n";
- $dicoDesTitres{$text}++;
- }
- else {
- $dicoDesTitres{$text}++;
- $DUMPFULL1.="<abstract>-</abstract>\n";
- }
- }
- }
- close(FILEIN);
- }
- }
- }
- }
- #----------------------------------------------
- sub nettoieText {
- my $texte=shift;
- $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;
- return $texte;
- }
#/usr/bin/perl <<DOC; Votre Nom : JANVIER 2015 usage : perl parcours-arborescence-fichiers repertoire-a-parcourir Le programme prend en entrée le nom du répertoire contenant les fichiers à traiter Le programme construit en sortie un fichier structuré contenant sur chaque ligne le nom du fichier et le résultat du filtrage : <FICHIER><NOM>du fichier</NOM></FICHIER><CONTENU>du filtrage</CONTENU></FICHIER> DOC #----------------------------------------------------------- my $rep="$ARGV[0]"; # on s'assure que le nom du répertoire ne se termine pas par un "/" $rep=~ s/[\/]$//; # on initialise une variable contenant le flux de sortie my $DUMPFULL1=""; my $DUMPFULL2=""; my $cptArticle=0; my %dicoDesTitres=(); my %dicoDesDescriptions=(); #---------------------------------------- my $output1="SORTIE.txt"; if (!open (FILEOUTTXT,">$output1")) { die "Pb a l'ouverture du fichier $output1"}; my $output2="SORTIE.xml"; if (!open (FILEOUTXML,">$output2")) { die "Pb a l'ouverture du fichier $output2"}; #---------------------------------------- &parcoursarborescencefichiers($rep); #recurse! #---------------------------------------- print FILEOUTXML "<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?>\n"; print FILEOUTXML "<PARCOURS>\n"; print FILEOUTXML "<NOM>SF</NOM>\n"; print FILEOUTXML "<FILTRAGE>".$DUMPFULL1."</FILTRAGE>\n"; print FILEOUTXML "</PARCOURS>\n"; close(FILEOUTXML); print FILEOUTTXT $DUMPFULL2; close(FILEOUTTXT); exit; #---------------------------------------------- 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); #recurse! } if (-f $file) { if ($file=~/\.xml$/) { print $i++,"\n"; open(FILEIN,$file); while (my $ligne=<FILEIN>) { if ($ligne=~/<\/item>/) { $DUMPFULL1.="</article>\n"; } if ($ligne=~/<item>/) { $cptArticle++; $DUMPFULL1.="<article numero=\"$cptArticle\">\n"; } if ($ligne=~/<description>(.+?)<\/description>/) { my $text=$1; $text=&nettoieText($text); if (!(exists($dicoDesDescriptions{$text}))) { $DUMPFULL1.="<description>$text</description>\n"; $DUMPFULL2.=$text."\n"; $dicoDesDescriptions{$text}++; } else { $dicoDesDescriptions{$text}++; $DUMPFULL1.="<description>-</description>\n"; } } if ($ligne=~/<title>(.+?)<\/title>/) { my $text=$1; $text=&nettoieText($text); if (!(exists($dicoDesTitres{$text}))) { $DUMPFULL1.="<abstract>$text</abstract>\n"; $DUMPFULL2.=$text."\n"; $dicoDesTitres{$text}++; } else { $dicoDesTitres{$text}++; $DUMPFULL1.="<abstract>-</abstract>\n"; } } } close(FILEIN); } } } } #---------------------------------------------- sub nettoieText { my $texte=shift; $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; return $texte; }
Nós apresentamos aqui uma segunda versão de CdF 1 que utiliza um dos módulos disponíveis em Perl. A razão pela qual nós distinguimos essas duas categorias é devido ao fato de que os módulos são programas adicionais já escritos em Perl que sevem ser baixados separadamanente. Isto pode ser feito feitos de várias maneiras diferentes que váriam em função do sistema operacional utilizado. Normalmente, a maneira fácil é utilizar um gerenciado de pacotes (como Homebrew para MacOs, Chocolatey para Windows, etc.) para poder baixar e instalar corretamente esses módulos com apenas alguns cliques.
Este script utiliza a abordagem "Módulos Perl". Nós utilizamos neste script os módulos XML::RSS e Unicode::String (atenção à diferença entre letras maiúsculas e minúsculas!). Desta forma nós podemos utilizar os analizadores (parser) de arquivos XML e converter o texto em utf-8. O script verifica a codificafação (em maiúsculo uc) na primeira linha da string "UTF-8" e caso ela não seja a mesma, nós utilizamos o módulo Unicode::String para converter o arquivo em utf-8. A outra grande diferença em relação ao outro programa onde nós utilizamos expressões regulares (regex) para extrair os títulos e as descrições, aqui nós utilizamos XML::RSS para fazê-lo (linhas 25-26). Ou seja, como no primeiro programa, nós nos certificamos que nós tratamos cada texto apenas uma vez e o texto é limpo, utilizando uma função que contém vários s///g para substituir os caracteres indesejáveis pelos seus equivalentes.
- #!/usr/bin/perl
- use XML::RSS;
- use Unicode::String qw(utf8);
- #----------------------------------------------------------
- my $encodagesortie="utf-8";
- my $encodage=`file -i $ARGV[0] | cut -d= -f2`;
- open(OUT1,">:encoding($encodagesortie)","sortie-textebrut-avec-xmlrss.txt");
- open(OUT2,">:encoding($encodagesortie)","sortie-textexml-avec-xmlrss.xml");
- print OUT2 "<?xml version=\"1.0\" encoding=\"$encodagesortie\" ?>\n";
- print OUT2 "<file>\n";
- print OUT2 "<name>$ARGV[0]</name>\n";
- #-----------------------------------------------------------
- my $file="$ARGV[0]";
- 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 {
- my $date=$rss->{'channel'}->{'pubDate'};
- print OUT2 "<date>$date</date>\n";
- print OUT2 "<items>\n";
- foreach my $item (@{$rss->{'items'}}) {
- my $titre=$item->{'title'};
- my $resume=$item->{'description'};
- $titre=&nettoietexte($titre);
- $resume=&nettoietexte($resume);
- if (uc($encodage) ne "UTF-8") {utf8($titre);utf8($resume);}
- print OUT1 "Titre : $titre \n";
- print OUT1 "Resume : $resume \n";;
- print OUT2
- "<item><title>$titre</title><abstract>$resume</abstract></item>\n";
- }
- }
- #----------------------------------------------------------
- print OUT2 "</items>\n</file>\n";
- close(OUT1);
- close(OUT2);
- close(FILE);
- exit;
- #----------------------------------------------------------
- #----------------------------------------------------------
- sub nettoietexte {
- my $texte=shift;
- $texte=~s/'/'/g;
- $texte=~s/"/"/g;
- $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;
- return $texte;
- }
#!/usr/bin/perl use XML::RSS; use Unicode::String qw(utf8); #---------------------------------------------------------- my $encodagesortie="utf-8"; my $encodage=`file -i $ARGV[0] | cut -d= -f2`; open(OUT1,">:encoding($encodagesortie)","sortie-textebrut-avec-xmlrss.txt"); open(OUT2,">:encoding($encodagesortie)","sortie-textexml-avec-xmlrss.xml"); print OUT2 "<?xml version=\"1.0\" encoding=\"$encodagesortie\" ?>\n"; print OUT2 "<file>\n"; print OUT2 "<name>$ARGV[0]</name>\n"; #----------------------------------------------------------- my $file="$ARGV[0]"; 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 { my $date=$rss->{'channel'}->{'pubDate'}; print OUT2 "<date>$date</date>\n"; print OUT2 "<items>\n"; foreach my $item (@{$rss->{'items'}}) { my $titre=$item->{'title'}; my $resume=$item->{'description'}; $titre=&nettoietexte($titre); $resume=&nettoietexte($resume); if (uc($encodage) ne "UTF-8") {utf8($titre);utf8($resume);} print OUT1 "Titre : $titre \n"; print OUT1 "Resume : $resume \n";; print OUT2 "<item><title>$titre</title><abstract>$resume</abstract></item>\n"; } } #---------------------------------------------------------- print OUT2 "</items>\n</file>\n"; close(OUT1); close(OUT2); close(FILE); exit; #---------------------------------------------------------- #---------------------------------------------------------- sub nettoietexte { my $texte=shift; $texte=~s/'/'/g; $texte=~s/"/"/g; $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; return $texte; }
Perl com XPATH
A terceira versão do script utiliza um módulo diferente: XML::XPath. Com a utilização desse módulo, nós temos um script que se assemelha mais com o script qui utiliza XML::RSS, exceto na diferença entre maiúsculas e minúsculas, o módulo utiliza XPath para analizar a estrutura XML e encontrar os elementos contidos nas tags buscadas. Este script cria igualmente duas saídas (XML e TXT) e limpa os dados com auxílio de uma função que substitui os caracteres indesejáveis por seus equivalentes.
- #/usr/bin/perl
- use XML::XPath;
- # On vérifie le nombre d'arguments de l'appel au script ($0 : le nom du script)
- if($#ARGV!=0){
- print "usage : perl $0 fichier_tag fichier_motif";
- exit; }
- #----------------------------------------------------------------------------------
- -----------------------------------------------------------------
- my $encodagesortie="utf-8";
- open(OUT1,">:encoding($encodagesortie)","sortie-textebrut-avec-xmlxpath.txt");
- open(OUT2,">:encoding($encodagesortie)","sortie-textexml-avec-xmlxpath.xml");
- print OUT2 "<?xml version=\"1.0\" encoding=\"$encodagesortie\" ?>\n";
- print OUT2 "<file>\n";
- print OUT2 "<name>$ARGV[0]</name>\n";
- my $input_file= shift @ARGV;
- my $xp = XML::XPath->new( filename => $input_file ) or die "big trouble";
- my $search_path.="//item";
- # boucle sur les nœuds reconnus du chemin xpath
- foreach my $noeud ( $xp->find($search_path)->get_nodelist ) {
- my $titre=$noeud->find('title')->string_value;
- my $resume=$noeud->find('description')->string_value;
- $titre=&nettoietexte($titre);
- $resume=&nettoietexte($resume);
- print OUT1 "Titre : $titre \n";
- print OUT1 "Resume : $resume \n";;
- print OUT2
- "<item><title>$titre</title><abstract>$resume</abstract></item>\n";
- }
- #----------------------------------------------------------
- print OUT2 "</items>\n</file>\n";
- close(OUT1);
- close(OUT2);
- close(FILE);
- exit;
- sub nettoietexte {
- my $texte=shift;
- $texte=~s/'/'/g;
- $texte=~s/"/"/g;
- $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;
- return $texte;
- }
#/usr/bin/perl use XML::XPath; # On vérifie le nombre d'arguments de l'appel au script ($0 : le nom du script) if($#ARGV!=0){ print "usage : perl $0 fichier_tag fichier_motif"; exit; } #---------------------------------------------------------------------------------- ----------------------------------------------------------------- my $encodagesortie="utf-8"; open(OUT1,">:encoding($encodagesortie)","sortie-textebrut-avec-xmlxpath.txt"); open(OUT2,">:encoding($encodagesortie)","sortie-textexml-avec-xmlxpath.xml"); print OUT2 "<?xml version=\"1.0\" encoding=\"$encodagesortie\" ?>\n"; print OUT2 "<file>\n"; print OUT2 "<name>$ARGV[0]</name>\n"; my $input_file= shift @ARGV; my $xp = XML::XPath->new( filename => $input_file ) or die "big trouble"; my $search_path.="//item"; # boucle sur les nœuds reconnus du chemin xpath foreach my $noeud ( $xp->find($search_path)->get_nodelist ) { my $titre=$noeud->find('title')->string_value; my $resume=$noeud->find('description')->string_value; $titre=&nettoietexte($titre); $resume=&nettoietexte($resume); print OUT1 "Titre : $titre \n"; print OUT1 "Resume : $resume \n";; print OUT2 "<item><title>$titre</title><abstract>$resume</abstract></item>\n"; } #---------------------------------------------------------- print OUT2 "</items>\n</file>\n"; close(OUT1); close(OUT2); close(FILE); exit; sub nettoietexte { my $texte=shift; $texte=~s/'/'/g; $texte=~s/"/"/g; $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; return $texte; }
Puro Perl
Nossa versão realiza as mesma tarefa, mas de uma maneira ligeiramente diferente. Como vocês podem notar, nossa versão é muito mais longa.Isso é em parte devido aos comentários que nós inserimos no código, mas também pela nossa função de limpeza (nettoietexte()**). Nós percebemos que haviam certos caracteres na saída que não estavam sendo exibidos corretamente. Portanto, nós adicionamos mais algumas expressões regulares para capturas essas exceções.
Nós também modificamos um aspecto mais importante do código. Nós excluímos a saída global que continha todos os temas juntos. Nós fizemos isso para cada tema possui o seu próprio arquivo(um XML e outro TXT) A separação dos dados dessa forma é especialmente importante para CdF 3. Colocar essa funcionalidade no código agora, simplifica a nossa tarefa mais adiante.
** Você perceberá que oo nomes de algumas variaveis são diferentes. A ideia, no entanto, é a mesma.
***O código não é 100% "Puro Perl", nós utilizamos o módulo Unicode::String para converter o texto em utf-8.
O código :
- #/usr/bin/perl
- use Unicode::String qw(utf8);
- #lire l'entrée standard
- my $rep="$ARGV[0]";
- # éliminier les possibles "/" à la fin du nom du dossier
- $rep=~ s/[\/]$//;
- # liste pour stocker les items déjà traités
- my %dictionnairedesitems = ();
- # liste pour stocker les rubriques déjà traités
- my %dictionnairesdesrubriques = ();
- # appeler la fonction extraire_rubrique() pour lire les dossiers et extraire les rubriques des fichiers
- &extraire_rubrique($rep);
- my @liste_rubriques = keys(%dictionnairesdesrubriques);
- # pour chaque rubrique, créer un fichier de sortie .xml et un fichier .txt
- foreach my $rub (@liste_rubriques) {
- my $output1= "SORTIE-extract-txt-".$rub.".xml";
- my $output2= "SORTIE-extract-txt-".$rub.".txt";
- # créer fichier .xml de sortie
- open (FILEOUTXML, ">:encoding(utf-8)", $output1) or die "Could not open file @output1!"; # open file for writing
- # créer fichier .txt de sortie
- open (FILEOUTTXT, ">:encoding(utf-8)", $output2) or die "Could not open file $output2!"; # open file for writing)
- # écrier déclaration d'en-tête du fichier xml
- print FILEOUTXML "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
- print FILEOUTXML "<PARCOURS>\n";
- #fermer les deux fichiers
- close(FILEOUTXML);
- close(FILEOUTTXT);
- print $output1;
- }
- # appeler lire_et_ecrire_xml() pour lire tous les fichiers xml et créer les sorties
- &lire_et_ecrire_xml($rep);
- foreach my $rub (@liste_rubriques)
- {
- my $output1="SORTIE-extract-txt-".$rub.".xml";
- if (!open (FILEOUTXML,">>:encoding(utf-8)", $output1))
- {
- die "Pb a l'ouverture du fichier $output1";
- }
- print FILEOUTXML "</PARCOURS>\n";
- close(FILEOUTXML);
- }
- exit;
- #########################################################################################################
- # #
- # cette fonction reçoit un nom de dossier comme argument et lit tous les fichiers .xml du dossier #
- # Pour chaque fichier lu, la fonction extrait les texte des balise <title> et <description>, ainsi que #
- # les dates présente en <pubDate> et <rubrique> #
- # Ce contenu insère dans des fichiers .xml et .txt de sortie de la rubrique correspondante #
- # #
- #########################################################################################################
- sub lire_et_ecrire_xml {
- # lire nom de dossier passé comme argument
- my $path = shift(@_);
- # ouvrir dossier
- opendir(DIR, $path) or die "can't open $path: $!\n";
- # lire itens dans le dossier
- my @files = readdir(DIR);
- closedir(DIR);
- # fermer dossier
- foreach my $file (@files)
- {
- # ignorer les items cachés
- next if $file =~ /^\.\.?$/;
- # construire le chemin complet avec le nom du dossier + item traité
- $file = $path."/".$file;
- # vérifier si l'item traité est dossier
- if (-d $file)
- {
- # si l'item qu'on est en train de traiter est un dossier, on recommence la procédure
- &lire_et_ecrire_xml($file);
- }
- # vérifier si l'item traité un fichier IF1
- if (-f $file)
- {
- # vérifier s'il s'agit d'un fichier .xml qui ne contient pas fil dans le nom iF2
- if (($file=~/\.xml$/) && ($file!~/\/fil.+\.xml$/))
- {
- # ouvrir fichier
- open(FILE, $file);
- # variable pour stocker le contenu du fichier
- my $texte="";
- #lire le contenu du fichier ligne à line
- while (my $ligne=<FILE>)
- {
- chomp $ligne;
- $texte .= $ligne;
- }
- # fermer fichier
- close(FILE);
- # regex pour capturer l'encodage du fichier
- $texte=~/encoding ?= ?[\'\"]([^\'\"]+)[\'\"]/i;
- # stocker l'encogade du fichier
- my $encodage=$1;
- # vérifier si l'encodage n'est pas vide pour traiter le contenu IF3
- if ($encodage ne "")
- {
- # la variable temptexteXML stocke les contenus prêts à être écrits dans fichier .xml de sortie
- my $tmptexteXML="<file>\n";
- # créer balise avec le nom du fichier
- $tmptexteXML.="<name>$file</name>\n";
- # éliminier les balises avec des espaces en blanc
- $texte =~ s/> *</></g;
- # regex pour capturer date
- $texte=~/<pubDate>([^<]+)<\/pubDate>/;
- # stocker la valeur de date capturée par la regex
- $tmptexteXML.="<date>$1</date>\n";
- # insérer la balise <items>
- $tmptexteXML.="<items>\n";
- my $tmptexteBRUT="";
- open(FILE,"<:encoding($encodage)", $file);
- $texte="";
- # lire le fichier ligne à ligne
- while (my $ligne=<FILE>)
- {
- chomp $ligne;
- $texte .= $ligne;
- }
- close(FILE);
- $texte=~s/> *</></g;
- # on recherche la rubrique
- $texte=~/<channel><title>([^<]+)<\/title>/;
- # nettoyer le string rubrique
- my $rub=$1;
- $rub =~ s/Toute l'actualité sur Le Monde.fr.//gi;
- $rub=~s/é/e/gi;
- $rub=~s/è/e/gi;
- $rub=~s/ê/e/gi;
- $rub=~s/à/a/gi;
- $rub=~ s/Le ?Monde.fr ?://;
- $rub=~ s/ //g;
- $rub=uc($rub);
- my $output1="SORTIE-extract-txt-".$rub.".xml";
- my $output2="SORTIE-extract-txt-".$rub.".txt";
- if (!open (FILEOUTXML,">>:encoding(utf-8)", $output1)) { die "Pb a l'ouverture du fichier $output1"};
- if (!open (FILEOUTTXT,">>:encoding(utf-8)", $output2)) { die "Pb a l'ouverture du fichier $output2"};
- # lire texte pour extraire contenu des balises <title> et <description>
- while ($texte =~ /<item><title>(.+?)<\/title>.+?<description>(.+?)<\/description>/g)
- {
- # capturer contenu de la regex pour titre
- my $titre=$1;
- # capturer contenu de la regex pour description
- my $resume=$2;
- #
- $titre = &nettoyer_texte($1);
- $resume = &nettoyer_texte($2);
- # si le fichier n'est pas en UTF-8, convertir le string $titre et $resume en UTF-8
- if (uc($encodage) ne "UTF-8")
- {
- utf8($titre);
- utf8($resume);
- }
- # si le contenu de $resume n'a pas encore été traite, on doit le traiter
- if (!(exists($dictionnairedesitems{$resume})))
- {
- # créer contenu le fichier .txt
- $tmptexteBRUT.="§ $titre \n";
- $tmptexteBRUT.="$resume \n";
- # créer contenu pour fichier .xml
- $tmptexteXML.="<item><title>$titre</title><abstract>$resume</abstract></item>\n";
- # inclure contenu de $resume dans liste
- $dictionnairedesitems{$resume}++;
- } else {
- $tmptexteXML.="<item><title>-</title><abstract>-</abstract></item>\n";
- }
- } # fin while
- # rajouter la fin des balise <items> et <file>
- $tmptexteXML.="</items>\n</file>\n";
- # écrire contenu dans le fichier .xml
- print FILEOUTXML $tmptexteXML;
- # écrire contenu dans le fichier .txt
- print FILEOUTTXT $tmptexteBRUT;
- # fermer fichiers
- close FILEOUTXML;
- close FILEOUTTXT;
- } else {
- #si l'encaodre est vide afficher message
- print "$file ==> $encodage \n";
- } # fin IF3
- } # fin IF 2
- } # fin IF 1
- } # fin FOR
- } # fin lire_et_ecrire_xml()
- sub nettoyer_texte {
- my $texte=shift;
- $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;
- $texte=~s/'/'/g;
- $texte=~s/"/"/g;
- $texte=~s/&#39;/'/g;
- $texte=~s/&#34;/"/g;
- return $texte;
- }
- ####################################################################################################
- # #
- # cette fonction reçoit un nom de dossier comme argument et lit tous les fichiers .xml du dossier #
- # Pour chaque fichier lu, la fonction extrait les rubriques et crée des fichiers de sortie #
- # possédant le nom de la rubrique #
- # #
- ####################################################################################################
- sub extraire_rubrique {
- #lire le nom dossier passé comme argument
- my $path = shift(@_);
- #ouvrir le dossier
- opendir(DIR, $path) or die "can't open $path: $!\n";
- #lire la liste de fichier du dossier
- my @files = readdir(DIR);
- closedir(DIR);
- # lire un à un les items du dossier
- foreach my $file (@files)
- {
- # ignorer les items cachés
- next if $file =~ /^\.\.?$/;
- # construire le chemin complet avec le nom du dossier + item traité
- $file = $path."/".$file;
- # vérifier si l'item est un dossier
- if (-d $file)
- {
- # si l'item qu'on est en train de traiter est un dossier, on recommence la procédure
- &extraire_rubrique($file);
- }
- # vérifier si l'item est un fichier - IF1
- if (-f $file)
- {
- # tester si fichier possède l'extension .xml et ne contient pas la substring fil dans le nom - IF2
- if (($file =~ /\.xml$/) && ($file!~/\/fil.+\.xml$/))
- {
- #ouvrir fichier .xml
- open(FILE,$file);
- #variable pour stocker le contenu du fichier .xml
- my $texte="";
- #lire toutes les lignes du fichier .xml
- while (my $ligne=<FILE>)
- {
- # effacer les retours à la ligne
- chomp $ligne;
- # stocker le contenu de ligne lue
- $texte .= $ligne;
- }
- # fermer le fichier .xml
- close(FILE);
- # regex pour capture l`encodage du fichier
- $texte =~ /encoding ?= ?[\'\"]([^\'\"]+)[\'\"]/i;
- # stocker le contenu trouvé par la regex
- my $encodage=$1;
- # vérifier la contenu de regex n'est pas vide IF3
- if ($encodage ne "")
- {
- # reouvrir le fichier avec l'encogade correcte
- open(FILE,"<:encoding($encodage)", $file);
- # variables pour stocker le contenu du fichier lu
- $texte="";
- # lire le fichier .xml
- while (my $ligne=<FILE>)
- {
- # effacer les retours à la ligne
- chomp $ligne;
- # stocker le contenu de ligne lue
- $texte .= $ligne;
- }
- # fermer le fichier .xml
- close(FILE);
- # effacer les espaces en blanc
- $texte =~ s/> *</></g;
- # capturer le contenu à l'intérieur des balises <title> - IF4
- if ($texte=~ /<channel><title>([^>]+)<\/title>/)
- {
- print $texte;
- # stocker la valeur de rubrique trouvée par la regex
- my $rub=$1;
- # nettoyer les noms des rubriques
- $rub =~ s/Toute l'actualité sur Le Monde.fr.//gi;
- $rub=~s/é/e/gi;
- $rub=~s/è/e/gi;
- $rub=~s/ê/e/gi;
- $rub=~s/à/a/gi;
- $rub=~ s/Le ?Monde.fr ?://i;
- $rub=~ s/ //g;
- $rub=uc($rub);
- # stocker la rubrique dans le dictionnaire des rubriques
- $dictionnairesdesrubriques{$rub}++;
- } # fin IF4
- } # fin IF3
- } # fin IF2
- } # fin IF1
- } # fin FOR
- } # fin extraire_rubrique()
#/usr/bin/perl use Unicode::String qw(utf8); #lire l'entrée standard my $rep="$ARGV[0]"; # éliminier les possibles "/" à la fin du nom du dossier $rep=~ s/[\/]$//; # liste pour stocker les items déjà traités my %dictionnairedesitems = (); # liste pour stocker les rubriques déjà traités my %dictionnairesdesrubriques = (); # appeler la fonction extraire_rubrique() pour lire les dossiers et extraire les rubriques des fichiers &extraire_rubrique($rep); my @liste_rubriques = keys(%dictionnairesdesrubriques); # pour chaque rubrique, créer un fichier de sortie .xml et un fichier .txt foreach my $rub (@liste_rubriques) { my $output1= "SORTIE-extract-txt-".$rub.".xml"; my $output2= "SORTIE-extract-txt-".$rub.".txt"; # créer fichier .xml de sortie open (FILEOUTXML, ">:encoding(utf-8)", $output1) or die "Could not open file @output1!"; # open file for writing # créer fichier .txt de sortie open (FILEOUTTXT, ">:encoding(utf-8)", $output2) or die "Could not open file $output2!"; # open file for writing) # écrier déclaration d'en-tête du fichier xml print FILEOUTXML "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"; print FILEOUTXML "<PARCOURS>\n"; #fermer les deux fichiers close(FILEOUTXML); close(FILEOUTTXT); print $output1; } # appeler lire_et_ecrire_xml() pour lire tous les fichiers xml et créer les sorties &lire_et_ecrire_xml($rep); foreach my $rub (@liste_rubriques) { my $output1="SORTIE-extract-txt-".$rub.".xml"; if (!open (FILEOUTXML,">>:encoding(utf-8)", $output1)) { die "Pb a l'ouverture du fichier $output1"; } print FILEOUTXML "</PARCOURS>\n"; close(FILEOUTXML); } exit; ######################################################################################################### # # # cette fonction reçoit un nom de dossier comme argument et lit tous les fichiers .xml du dossier # # Pour chaque fichier lu, la fonction extrait les texte des balise <title> et <description>, ainsi que # # les dates présente en <pubDate> et <rubrique> # # Ce contenu insère dans des fichiers .xml et .txt de sortie de la rubrique correspondante # # # ######################################################################################################### sub lire_et_ecrire_xml { # lire nom de dossier passé comme argument my $path = shift(@_); # ouvrir dossier opendir(DIR, $path) or die "can't open $path: $!\n"; # lire itens dans le dossier my @files = readdir(DIR); closedir(DIR); # fermer dossier foreach my $file (@files) { # ignorer les items cachés next if $file =~ /^\.\.?$/; # construire le chemin complet avec le nom du dossier + item traité $file = $path."/".$file; # vérifier si l'item traité est dossier if (-d $file) { # si l'item qu'on est en train de traiter est un dossier, on recommence la procédure &lire_et_ecrire_xml($file); } # vérifier si l'item traité un fichier IF1 if (-f $file) { # vérifier s'il s'agit d'un fichier .xml qui ne contient pas fil dans le nom iF2 if (($file=~/\.xml$/) && ($file!~/\/fil.+\.xml$/)) { # ouvrir fichier open(FILE, $file); # variable pour stocker le contenu du fichier my $texte=""; #lire le contenu du fichier ligne à line while (my $ligne=<FILE>) { chomp $ligne; $texte .= $ligne; } # fermer fichier close(FILE); # regex pour capturer l'encodage du fichier $texte=~/encoding ?= ?[\'\"]([^\'\"]+)[\'\"]/i; # stocker l'encogade du fichier my $encodage=$1; # vérifier si l'encodage n'est pas vide pour traiter le contenu IF3 if ($encodage ne "") { # la variable temptexteXML stocke les contenus prêts à être écrits dans fichier .xml de sortie my $tmptexteXML="<file>\n"; # créer balise avec le nom du fichier $tmptexteXML.="<name>$file</name>\n"; # éliminier les balises avec des espaces en blanc $texte =~ s/> *</></g; # regex pour capturer date $texte=~/<pubDate>([^<]+)<\/pubDate>/; # stocker la valeur de date capturée par la regex $tmptexteXML.="<date>$1</date>\n"; # insérer la balise <items> $tmptexteXML.="<items>\n"; my $tmptexteBRUT=""; open(FILE,"<:encoding($encodage)", $file); $texte=""; # lire le fichier ligne à ligne while (my $ligne=<FILE>) { chomp $ligne; $texte .= $ligne; } close(FILE); $texte=~s/> *</></g; # on recherche la rubrique $texte=~/<channel><title>([^<]+)<\/title>/; # nettoyer le string rubrique my $rub=$1; $rub =~ s/Toute l'actualité sur Le Monde.fr.//gi; $rub=~s/é/e/gi; $rub=~s/è/e/gi; $rub=~s/ê/e/gi; $rub=~s/à/a/gi; $rub=~ s/Le ?Monde.fr ?://; $rub=~ s/ //g; $rub=uc($rub); my $output1="SORTIE-extract-txt-".$rub.".xml"; my $output2="SORTIE-extract-txt-".$rub.".txt"; if (!open (FILEOUTXML,">>:encoding(utf-8)", $output1)) { die "Pb a l'ouverture du fichier $output1"}; if (!open (FILEOUTTXT,">>:encoding(utf-8)", $output2)) { die "Pb a l'ouverture du fichier $output2"}; # lire texte pour extraire contenu des balises <title> et <description> while ($texte =~ /<item><title>(.+?)<\/title>.+?<description>(.+?)<\/description>/g) { # capturer contenu de la regex pour titre my $titre=$1; # capturer contenu de la regex pour description my $resume=$2; # $titre = &nettoyer_texte($1); $resume = &nettoyer_texte($2); # si le fichier n'est pas en UTF-8, convertir le string $titre et $resume en UTF-8 if (uc($encodage) ne "UTF-8") { utf8($titre); utf8($resume); } # si le contenu de $resume n'a pas encore été traite, on doit le traiter if (!(exists($dictionnairedesitems{$resume}))) { # créer contenu le fichier .txt $tmptexteBRUT.="§ $titre \n"; $tmptexteBRUT.="$resume \n"; # créer contenu pour fichier .xml $tmptexteXML.="<item><title>$titre</title><abstract>$resume</abstract></item>\n"; # inclure contenu de $resume dans liste $dictionnairedesitems{$resume}++; } else { $tmptexteXML.="<item><title>-</title><abstract>-</abstract></item>\n"; } } # fin while # rajouter la fin des balise <items> et <file> $tmptexteXML.="</items>\n</file>\n"; # écrire contenu dans le fichier .xml print FILEOUTXML $tmptexteXML; # écrire contenu dans le fichier .txt print FILEOUTTXT $tmptexteBRUT; # fermer fichiers close FILEOUTXML; close FILEOUTTXT; } else { #si l'encaodre est vide afficher message print "$file ==> $encodage \n"; } # fin IF3 } # fin IF 2 } # fin IF 1 } # fin FOR } # fin lire_et_ecrire_xml() sub nettoyer_texte { my $texte=shift; $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; $texte=~s/'/'/g; $texte=~s/"/"/g; $texte=~s/&#39;/'/g; $texte=~s/&#34;/"/g; return $texte; } #################################################################################################### # # # cette fonction reçoit un nom de dossier comme argument et lit tous les fichiers .xml du dossier # # Pour chaque fichier lu, la fonction extrait les rubriques et crée des fichiers de sortie # # possédant le nom de la rubrique # # # #################################################################################################### sub extraire_rubrique { #lire le nom dossier passé comme argument my $path = shift(@_); #ouvrir le dossier opendir(DIR, $path) or die "can't open $path: $!\n"; #lire la liste de fichier du dossier my @files = readdir(DIR); closedir(DIR); # lire un à un les items du dossier foreach my $file (@files) { # ignorer les items cachés next if $file =~ /^\.\.?$/; # construire le chemin complet avec le nom du dossier + item traité $file = $path."/".$file; # vérifier si l'item est un dossier if (-d $file) { # si l'item qu'on est en train de traiter est un dossier, on recommence la procédure &extraire_rubrique($file); } # vérifier si l'item est un fichier - IF1 if (-f $file) { # tester si fichier possède l'extension .xml et ne contient pas la substring fil dans le nom - IF2 if (($file =~ /\.xml$/) && ($file!~/\/fil.+\.xml$/)) { #ouvrir fichier .xml open(FILE,$file); #variable pour stocker le contenu du fichier .xml my $texte=""; #lire toutes les lignes du fichier .xml while (my $ligne=<FILE>) { # effacer les retours à la ligne chomp $ligne; # stocker le contenu de ligne lue $texte .= $ligne; } # fermer le fichier .xml close(FILE); # regex pour capture l`encodage du fichier $texte =~ /encoding ?= ?[\'\"]([^\'\"]+)[\'\"]/i; # stocker le contenu trouvé par la regex my $encodage=$1; # vérifier la contenu de regex n'est pas vide IF3 if ($encodage ne "") { # reouvrir le fichier avec l'encogade correcte open(FILE,"<:encoding($encodage)", $file); # variables pour stocker le contenu du fichier lu $texte=""; # lire le fichier .xml while (my $ligne=<FILE>) { # effacer les retours à la ligne chomp $ligne; # stocker le contenu de ligne lue $texte .= $ligne; } # fermer le fichier .xml close(FILE); # effacer les espaces en blanc $texte =~ s/> *</></g; # capturer le contenu à l'intérieur des balises <title> - IF4 if ($texte=~ /<channel><title>([^>]+)<\/title>/) { print $texte; # stocker la valeur de rubrique trouvée par la regex my $rub=$1; # nettoyer les noms des rubriques $rub =~ s/Toute l'actualité sur Le Monde.fr.//gi; $rub=~s/é/e/gi; $rub=~s/è/e/gi; $rub=~s/ê/e/gi; $rub=~s/à/a/gi; $rub=~ s/Le ?Monde.fr ?://i; $rub=~ s/ //g; $rub=uc($rub); # stocker la rubrique dans le dictionnaire des rubriques $dictionnairesdesrubriques{$rub}++; } # fin IF4 } # fin IF3 } # fin IF2 } # fin IF1 } # fin FOR } # fin extraire_rubrique()
Módulos Perl
A utilização dos módulos XML::Entities e HTML::Entities serve para modificar as entidades XML e HTML, códigos especiais que permitem a exibição de caracteres reservados em função do formato do documento (no nosso caso XML e HTML) nas suas representações gráficas reais. Por exemplo, "<" é um caracter especial em HTML e em XML que indica a aberta de uma tag. Para evitar que ele seja confundido com a abertura de uma tag no arquivo, nós dispomos das entidade. Desta forma ele não é interpretado de maneira incorreta, o que geraria o um arquivo mal formado. É por isso que vários outros caracteres "<" são indicados por "‹" no arquivo. Isso permite a distinção entre o que faz parte da estrura e aquilo faz parte do conteúdo do arquivo.
A utilização desses módulos nos script em Perl é feita da mesma maneira, XML::Entities sendo baseado em HTML::Entities. Para decodificar as entidades, só precisamos declarar os módulos da seguinte maneira:
A utilização é feita de seguinte maneira:
Para a ferramenta 1, nós escrevemos scripts em Perl utilizando as funções para excluir as entidades existentes nos arquivos, mas também os módulos XML::Entities e HTML::Entites. Nós temos dois scripts para Ferramenta 1 e Ferramenta 2, ou seja com e sem os módulos.
Nós percebemos que haviam tags de imagens dentros das tags de descrição. Mas o problema é que essas tags não estavam em codificadas como tags. Portanto, nós terminávamos por encontrar essas tags na saída final, o que é não era interessante para nosso resultado. Nós tivemos, então, que realizar um limpeza dos arquivos de resultado após a decodificação das entidades das tags de descrição.
- #/usr/bin/perl
- use Unicode::String qw(utf8);
- use XML::Entities;
- use HTML::Entities;
- use XML::RSS;
- #lire l'entrée standard
- my $rep="$ARGV[0]";
- # éliminier les possibles "/" à la fin du nom du dossier
- $rep=~ s/[\/]$//;
- # liste pour stocker les items déjà traités
- my %dictionnairedesitems = ();
- # liste pour stocker les rubriques déjà traités
- my %dictionnairesdesrubriques = ();
- # appeler la fonction extraire_rubrique() pour lire les dossiers et extraire les rubriques des fichiers
- &extraire_rubrique($rep);
- my @liste_rubriques = keys(%dictionnairesdesrubriques);
- # pour chaque rubrique, créer un fichier de sortie .xml et un fichier .txt
- foreach my $rub (@liste_rubriques) {
- my $output1= "SORTIE-extract-txt-".$rub.".xml";
- my $output2= "SORTIE-extract-txt-".$rub.".txt";
- # créer fichier .xml de sortie
- open (FILEOUTXML, ">:encoding(utf-8)", $output1) or die "Could not open file @output1!"; # open file for writing
- # créer fichier .txt de sortie
- open (FILEOUTTXT, ">:encoding(utf-8)", $output2) or die "Could not open file $output2!"; # open file for writing)
- # écrier déclaration d'en-tête du fichier xml
- print FILEOUTXML "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
- print FILEOUTXML "<PARCOURS>\n";
- #fermer les deux fichiers
- close(FILEOUTXML);
- close(FILEOUTTXT);
- print $output1;
- }
- # appeler lire_et_ecrire_xml() pour lire tous les fichiers xml et créer les sorties
- &lire_et_ecrire_xml($rep);
- foreach my $rub (@liste_rubriques)
- {
- my $output1="SORTIE-extract-txt-".$rub.".xml";
- if (!open (FILEOUTXML,">>:encoding(utf-8)", $output1))
- {
- die "Pb a l'ouverture du fichier $output1";
- }
- print FILEOUTXML "</PARCOURS>\n";
- close(FILEOUTXML);
- }
- exit;
- #########################################################################################################
- # #
- # cette fonction reçoit un nom de dossier comme argument et lit tous les fichiers .xml du dossier #
- # Pour chaque fichier lu, la fonction extrait le texte des balises <title> et <description>, ainsi que #
- # les dates présentes entre <pubDate> et <rubrique> #
- # Ce contenu insère dans des fichiers de sortie .xml et .txt la rubrique correspondante #
- # #
- #########################################################################################################
- sub lire_et_ecrire_xml {
- # lire nom de dossier passé comme argument
- my $path = shift(@_);
- # ouvrir dossier
- opendir(DIR, $path) or die "can't open $path: $!\n";
- # lire items dans le dossier
- my @files = readdir(DIR);
- closedir(DIR);
- # fermer dossier
- foreach my $file (@files)
- {
- # ignorer les items cachés
- next if $file =~ /^\.\.?$/;
- # construire le chemin complet avec le nom du dossier + item traité
- $file = $path."/".$file;
- # vérifier si l'item traité est un dossier
- if (-d $file)
- {
- # si l'item qu'on est en train de traiter est un dossier, on recommence la procédure
- &lire_et_ecrire_xml($file);
- }
- # vérifier si l'item traité un fichier IF1
- if (-f $file)
- {
- # vérifier s'il s'agit d'un fichier .xml qui ne contient pas fil dans le nom iF2
- if (($file=~/\.xml$/) && ($file!~/\/fil.+\.xml$/))
- {
- # ouvrir fichier
- open(FILE, $file);
- # variable pour stocker le contenu du fichier
- my $texte="";
- #lire le contenu du fichier ligne à line
- while (my $ligne=<FILE>)
- {
- chomp $ligne;
- $texte .= $ligne;
- }
- # fermer fichier
- close(FILE);
- # regex pour capturer l'encodage du fichier
- $texte=~/encoding ?= ?[\'\"]([^\'\"]+)[\'\"]/i;
- # stocker l'encodage du fichier
- my $encodage=$1;
- # vérifier si l'encodage n'est pas vide pour traiter le contenu IF3
- if ($encodage ne "")
- {
- # la variable tmptexteXML stocke les contenus prêts à être écrits dans fichier .xml de sortie
- my $tmptexteXML="<file>\n";
- # créer balise avec le nom du fichier
- $tmptexteXML.="<name>$file</name>\n";
- # éliminier les balises avec des espaces en blanc
- $texte =~ s/> *</></g;
- # regex pour capturer date
- $texte=~/<pubDate>([^<]+)<\/pubDate>/;
- # stocker la valeur de date capturée par la regex
- $tmptexteXML.="<date>$1</date>\n";
- # insérer la balise <items>
- $tmptexteXML.="<items>\n";
- my $tmptexteBRUT="";
- open(FILE,"<:encoding($encodage)", $file);
- $texte="";
- # lire le fichier ligne à ligne
- while (my $ligne=<FILE>)
- {
- chomp $ligne;
- $texte .= $ligne;
- }
- close(FILE);
- $texte=~s/> *</></g;
- # on recherche la rubrique
- $texte=~/<channel><title>([^<]+)<\/title>/;
- # on met le contenu trouvé par la regex dans $rub
- my $rub=$1;
- # nettoyer le string rubrique
- $rub =~ s/Toute l'actualité sur Le Monde.fr.//gi;
- $rub =~ s/é/e/gi;
- $rub =~ s/è/e/gi;
- $rub =~ s/ê/e/gi;
- $rub =~ s/à/a/gi;
- $rub =~ s/Le ?Monde.fr ?://;
- $rub =~ s/ //g;
- $rub=uc($rub);
- my $output1="SORTIE-extract-txt-".$rub.".xml";
- my $output2="SORTIE-extract-txt-".$rub.".txt";
- if (!open (FILEOUTXML,">>:encoding(utf-8)", $output1)) { die "Pb a l'ouverture du fichier $output1"};
- if (!open (FILEOUTTXT,">>:encoding(utf-8)", $output2)) { die "Pb a l'ouverture du fichier $output2"};
- # lire texte pour extraire contenu des balises <title> et <description>
- while ($texte =~ /<item><title>(.+?)<\/title>.+?<description>(.+?)<\/description>/g)
- {
- # capturer contenu de la regex pour titre
- my $titre=$1;
- # capturer contenu de la regex pour description
- my $resume=$2;
- # utilisation des modules pour remplacer dans les fichiers les entités XML et HTML
- if (!(exists ($dictionnairedesitems{$titre})) and !(exists ($dictionnairedesitems{$resume})))
- {
- $dictionnairedesitems{$titre}++;
- $dictionnairedesitems{$resume}++;
- $titre = XML::Entities::decode('all', $titre);
- $resume = XML::Entities::decode('all', $resume);
- $titre = HTML::Entities::decode($titre);
- $resume = HTML::Entities::decode($resume);
- $tmptexteBRUT.="$titre \n";
- $tmptexteBRUT.="$resume \n";
- $tmptexteXML.="<item><title>$titre</title><description>$resume</description></item>\n";
- # nettoyage des balises <description> pour supprimer les balises superflues
- $tmptexteXML =~ s/<img.*?\/><\/description>/<\/description>/g;
- $tmptexteBRUT =~ s/<img.*?\/> \n/\n/g;
- }
- # si le fichier n'est pas en UTF-8, convertir le string $titre et $resume en UTF-8
- if (uc($encodage) ne "UTF-8")
- {
- utf8($titre);
- utf8($resume);
- }
- } # fin while
- # rajouter la fin des balises <items> et <file>
- $tmptexteXML.="</items>\n</file>\n";
- # écrire contenu dans le fichier .xml
- print FILEOUTXML $tmptexteXML;
- # écrire contenu dans le fichier .txt
- print FILEOUTTXT $tmptexteBRUT;
- # fermer fichiers
- close FILEOUTXML;
- close FILEOUTTXT;
- } else {
- #si l'encodage est vide afficher message
- print "$file ==> $encodage \n";
- } # fin IF3
- } # fin IF 2
- } # fin IF 1
- } # fin FOR
- } # fin lire_et_ecrire_xml()
- ####################################################################################################
- # #
- # cette fonction reçoit un nom de dossier comme argument et lit tous les fichiers .xml du dossier #
- # Pour chaque fichier lu, la fonction extrait les rubriques et crée des fichiers de sortie #
- # possédant le nom de la rubrique #
- # #
- ####################################################################################################
- sub extraire_rubrique {
- #lire le nom dossier passé comme argument
- my $path = shift(@_);
- #ouvrir le dossier
- opendir(DIR, $path) or die "can't open $path: $!\n";
- #lire la liste de fichier du dossier
- my @files = readdir(DIR);
- closedir(DIR);
- # lire un à un les items du dossier
- foreach my $file (@files)
- {
- # ignorer les items cachés
- next if $file =~ /^\.\.?$/;
- # construire le chemin complet avec le nom du dossier + item traité
- $file = $path."/".$file;
- # vérifier si l'item est un dossier
- if (-d $file)
- {
- # si l'item qu'on est en train de traiter est un dossier, on recommence la procédure
- &extraire_rubrique($file);
- }
- # vérifier si l'item est un fichier - IF1
- if (-f $file)
- {
- # tester si fichier possède l'extension .xml et ne contient pas la substring fil dans le nom - IF2
- if (($file =~ /\.xml$/) && ($file!~/\/fil.+\.xml$/))
- {
- #ouvrir fichier .xml
- open(FILE,$file);
- #variable pour stocker le contenu du fichier .xml
- my $texte="";
- #lire toutes les lignes du fichier .xml
- while (my $ligne=<FILE>)
- {
- # effacer les retours à la ligne
- chomp $ligne;
- # stocker le contenu de ligne lue
- $texte .= $ligne;
- }
- # fermer le fichier .xml
- close(FILE);
- # regex pour capture l`encodage du fichier
- $texte =~ /encoding ?= ?[\'\"]([^\'\"]+)[\'\"]/i;
- # stocker le contenu trouvé par la regex
- my $encodage=$1;
- # vérifier la contenu de regex n'est pas vide IF3
- if ($encodage ne "")
- {
- # reouvrir le fichier avec l'encogade correcte
- open(FILE,"<:encoding($encodage)", $file);
- # variables pour stocker le contenu du fichier lu
- $texte="";
- # lire le fichier .xml
- while (my $ligne=<FILE>)
- {
- # effacer les retours à la ligne
- chomp $ligne;
- # stocker le contenu de ligne lue
- $texte .= $ligne;
- }
- # fermer le fichier .xml
- close(FILE);
- # effacer les espaces en blanc
- $texte =~ s/> *</></g;
- # capturer le contenu à l'intérieur des balises <title> - IF4
- if ($texte=~ /<channel><title>([^>]+)<\/title>/)
- {
- print $texte;
- # stocker la valeur de rubrique trouvée par la regex
- my $rub=$1;
- # nettoyer les noms des rubriques
- $rub =~ s/Toute l'actualité sur Le Monde.fr.//gi;
- $rub =~ s/é/e/gi;
- $rub =~ s/è/e/gi;
- $rub =~ s/ê/e/gi;
- $rub =~ s/à/a/gi;
- $rub =~ s/Le ?Monde.fr ?://;
- $rub =~ s/ //g;
- $rub=uc($rub);
- # stocker la rubrique dans le dictionnaire des rubriques
- $dictionnairesdesrubriques{$rub}++;
- } # fin IF4
- } # fin IF3
- } # fin IF2
- } # fin IF1
- } # fin FOR
- } # fin extraire_rubrique()
#/usr/bin/perl use Unicode::String qw(utf8); use XML::Entities; use HTML::Entities; use XML::RSS; #lire l'entrée standard my $rep="$ARGV[0]"; # éliminier les possibles "/" à la fin du nom du dossier $rep=~ s/[\/]$//; # liste pour stocker les items déjà traités my %dictionnairedesitems = (); # liste pour stocker les rubriques déjà traités my %dictionnairesdesrubriques = (); # appeler la fonction extraire_rubrique() pour lire les dossiers et extraire les rubriques des fichiers &extraire_rubrique($rep); my @liste_rubriques = keys(%dictionnairesdesrubriques); # pour chaque rubrique, créer un fichier de sortie .xml et un fichier .txt foreach my $rub (@liste_rubriques) { my $output1= "SORTIE-extract-txt-".$rub.".xml"; my $output2= "SORTIE-extract-txt-".$rub.".txt"; # créer fichier .xml de sortie open (FILEOUTXML, ">:encoding(utf-8)", $output1) or die "Could not open file @output1!"; # open file for writing # créer fichier .txt de sortie open (FILEOUTTXT, ">:encoding(utf-8)", $output2) or die "Could not open file $output2!"; # open file for writing) # écrier déclaration d'en-tête du fichier xml print FILEOUTXML "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"; print FILEOUTXML "<PARCOURS>\n"; #fermer les deux fichiers close(FILEOUTXML); close(FILEOUTTXT); print $output1; } # appeler lire_et_ecrire_xml() pour lire tous les fichiers xml et créer les sorties &lire_et_ecrire_xml($rep); foreach my $rub (@liste_rubriques) { my $output1="SORTIE-extract-txt-".$rub.".xml"; if (!open (FILEOUTXML,">>:encoding(utf-8)", $output1)) { die "Pb a l'ouverture du fichier $output1"; } print FILEOUTXML "</PARCOURS>\n"; close(FILEOUTXML); } exit; ######################################################################################################### # # # cette fonction reçoit un nom de dossier comme argument et lit tous les fichiers .xml du dossier # # Pour chaque fichier lu, la fonction extrait le texte des balises <title> et <description>, ainsi que # # les dates présentes entre <pubDate> et <rubrique> # # Ce contenu insère dans des fichiers de sortie .xml et .txt la rubrique correspondante # # # ######################################################################################################### sub lire_et_ecrire_xml { # lire nom de dossier passé comme argument my $path = shift(@_); # ouvrir dossier opendir(DIR, $path) or die "can't open $path: $!\n"; # lire items dans le dossier my @files = readdir(DIR); closedir(DIR); # fermer dossier foreach my $file (@files) { # ignorer les items cachés next if $file =~ /^\.\.?$/; # construire le chemin complet avec le nom du dossier + item traité $file = $path."/".$file; # vérifier si l'item traité est un dossier if (-d $file) { # si l'item qu'on est en train de traiter est un dossier, on recommence la procédure &lire_et_ecrire_xml($file); } # vérifier si l'item traité un fichier IF1 if (-f $file) { # vérifier s'il s'agit d'un fichier .xml qui ne contient pas fil dans le nom iF2 if (($file=~/\.xml$/) && ($file!~/\/fil.+\.xml$/)) { # ouvrir fichier open(FILE, $file); # variable pour stocker le contenu du fichier my $texte=""; #lire le contenu du fichier ligne à line while (my $ligne=<FILE>) { chomp $ligne; $texte .= $ligne; } # fermer fichier close(FILE); # regex pour capturer l'encodage du fichier $texte=~/encoding ?= ?[\'\"]([^\'\"]+)[\'\"]/i; # stocker l'encodage du fichier my $encodage=$1; # vérifier si l'encodage n'est pas vide pour traiter le contenu IF3 if ($encodage ne "") { # la variable tmptexteXML stocke les contenus prêts à être écrits dans fichier .xml de sortie my $tmptexteXML="<file>\n"; # créer balise avec le nom du fichier $tmptexteXML.="<name>$file</name>\n"; # éliminier les balises avec des espaces en blanc $texte =~ s/> *</></g; # regex pour capturer date $texte=~/<pubDate>([^<]+)<\/pubDate>/; # stocker la valeur de date capturée par la regex $tmptexteXML.="<date>$1</date>\n"; # insérer la balise <items> $tmptexteXML.="<items>\n"; my $tmptexteBRUT=""; open(FILE,"<:encoding($encodage)", $file); $texte=""; # lire le fichier ligne à ligne while (my $ligne=<FILE>) { chomp $ligne; $texte .= $ligne; } close(FILE); $texte=~s/> *</></g; # on recherche la rubrique $texte=~/<channel><title>([^<]+)<\/title>/; # on met le contenu trouvé par la regex dans $rub my $rub=$1; # nettoyer le string rubrique $rub =~ s/Toute l'actualité sur Le Monde.fr.//gi; $rub =~ s/é/e/gi; $rub =~ s/è/e/gi; $rub =~ s/ê/e/gi; $rub =~ s/à/a/gi; $rub =~ s/Le ?Monde.fr ?://; $rub =~ s/ //g; $rub=uc($rub); my $output1="SORTIE-extract-txt-".$rub.".xml"; my $output2="SORTIE-extract-txt-".$rub.".txt"; if (!open (FILEOUTXML,">>:encoding(utf-8)", $output1)) { die "Pb a l'ouverture du fichier $output1"}; if (!open (FILEOUTTXT,">>:encoding(utf-8)", $output2)) { die "Pb a l'ouverture du fichier $output2"}; # lire texte pour extraire contenu des balises <title> et <description> while ($texte =~ /<item><title>(.+?)<\/title>.+?<description>(.+?)<\/description>/g) { # capturer contenu de la regex pour titre my $titre=$1; # capturer contenu de la regex pour description my $resume=$2; # utilisation des modules pour remplacer dans les fichiers les entités XML et HTML if (!(exists ($dictionnairedesitems{$titre})) and !(exists ($dictionnairedesitems{$resume}))) { $dictionnairedesitems{$titre}++; $dictionnairedesitems{$resume}++; $titre = XML::Entities::decode('all', $titre); $resume = XML::Entities::decode('all', $resume); $titre = HTML::Entities::decode($titre); $resume = HTML::Entities::decode($resume); $tmptexteBRUT.="$titre \n"; $tmptexteBRUT.="$resume \n"; $tmptexteXML.="<item><title>$titre</title><description>$resume</description></item>\n"; # nettoyage des balises <description> pour supprimer les balises superflues $tmptexteXML =~ s/<img.*?\/><\/description>/<\/description>/g; $tmptexteBRUT =~ s/<img.*?\/> \n/\n/g; } # si le fichier n'est pas en UTF-8, convertir le string $titre et $resume en UTF-8 if (uc($encodage) ne "UTF-8") { utf8($titre); utf8($resume); } } # fin while # rajouter la fin des balises <items> et <file> $tmptexteXML.="</items>\n</file>\n"; # écrire contenu dans le fichier .xml print FILEOUTXML $tmptexteXML; # écrire contenu dans le fichier .txt print FILEOUTTXT $tmptexteBRUT; # fermer fichiers close FILEOUTXML; close FILEOUTTXT; } else { #si l'encodage est vide afficher message print "$file ==> $encodage \n"; } # fin IF3 } # fin IF 2 } # fin IF 1 } # fin FOR } # fin lire_et_ecrire_xml() #################################################################################################### # # # cette fonction reçoit un nom de dossier comme argument et lit tous les fichiers .xml du dossier # # Pour chaque fichier lu, la fonction extrait les rubriques et crée des fichiers de sortie # # possédant le nom de la rubrique # # # #################################################################################################### sub extraire_rubrique { #lire le nom dossier passé comme argument my $path = shift(@_); #ouvrir le dossier opendir(DIR, $path) or die "can't open $path: $!\n"; #lire la liste de fichier du dossier my @files = readdir(DIR); closedir(DIR); # lire un à un les items du dossier foreach my $file (@files) { # ignorer les items cachés next if $file =~ /^\.\.?$/; # construire le chemin complet avec le nom du dossier + item traité $file = $path."/".$file; # vérifier si l'item est un dossier if (-d $file) { # si l'item qu'on est en train de traiter est un dossier, on recommence la procédure &extraire_rubrique($file); } # vérifier si l'item est un fichier - IF1 if (-f $file) { # tester si fichier possède l'extension .xml et ne contient pas la substring fil dans le nom - IF2 if (($file =~ /\.xml$/) && ($file!~/\/fil.+\.xml$/)) { #ouvrir fichier .xml open(FILE,$file); #variable pour stocker le contenu du fichier .xml my $texte=""; #lire toutes les lignes du fichier .xml while (my $ligne=<FILE>) { # effacer les retours à la ligne chomp $ligne; # stocker le contenu de ligne lue $texte .= $ligne; } # fermer le fichier .xml close(FILE); # regex pour capture l`encodage du fichier $texte =~ /encoding ?= ?[\'\"]([^\'\"]+)[\'\"]/i; # stocker le contenu trouvé par la regex my $encodage=$1; # vérifier la contenu de regex n'est pas vide IF3 if ($encodage ne "") { # reouvrir le fichier avec l'encogade correcte open(FILE,"<:encoding($encodage)", $file); # variables pour stocker le contenu du fichier lu $texte=""; # lire le fichier .xml while (my $ligne=<FILE>) { # effacer les retours à la ligne chomp $ligne; # stocker le contenu de ligne lue $texte .= $ligne; } # fermer le fichier .xml close(FILE); # effacer les espaces en blanc $texte =~ s/> *</></g; # capturer le contenu à l'intérieur des balises <title> - IF4 if ($texte=~ /<channel><title>([^>]+)<\/title>/) { print $texte; # stocker la valeur de rubrique trouvée par la regex my $rub=$1; # nettoyer les noms des rubriques $rub =~ s/Toute l'actualité sur Le Monde.fr.//gi; $rub =~ s/é/e/gi; $rub =~ s/è/e/gi; $rub =~ s/ê/e/gi; $rub =~ s/à/a/gi; $rub =~ s/Le ?Monde.fr ?://; $rub =~ s/ //g; $rub=uc($rub); # stocker la rubrique dans le dictionnaire des rubriques $dictionnairesdesrubriques{$rub}++; } # fin IF4 } # fin IF3 } # fin IF2 } # fin IF1 } # fin FOR } # fin extraire_rubrique()
Exemplo dos resultados da ferramenta 1
Este é nosso resultado, uma vez que os caracteres reservados foram substituídos. Perceba que nós temos caracteres acentuados e não há tags de imagem!
Exemplo de uma saída XML.
Para facilitar a leitura dos resultados nós criamos uma folha de estilos xsl que pode ser encontrada aqui.
Este é o nosso resultado com exibição promovida pela folha de estilos.
O texto bruto contém apenas isso: texto. Ter um resultado com apenas texto sem nenhuma informação adicional de formatação é muito útil para a próxima etapa, onde nós utilizaremos o etiquetados (POS Tagger) Cordial e TreeTagger.
Exemplo de um resultado TXT.
O que a ferramenta 2 faz?
A ferramenta 2 é um programa que adiciona à ferramenta 1 o texto contido nas tags <title> e <description> com auxílio dos etiquetadores TreeTagger e Cordial.
O programa possui várias saídas, mas elas podem ser divididas em dois grupos principais. Um que é o mesmo resultado da ferramenta 1, texto bruto para cada categoria e arquivo XML. O outro grupo contém a saída etiquetada pelo TreeTagger convertida em um formato XML. Esse arquivo é organizado por linhas e palavras. Cada palavra presente em uma linha está associada com a sua etiqueta morfosintática e o seu lema.
Nós criamos também um arquivo global, conteando todas as categorias diferentes concatenadas nos mesmo arquivos.
A segunda parte da ferramenta 2 é feita manualmente. Cada um dos arquivos de texto bruto é convertido para iso-8859-15 (Latin 9) para ser compatível com Cordial. Observe que o caracter "œ" precisa ser substituído por "oe", já que ele não é suportado pela versão do Cordial utilizada para a realização do projeto.
O arquivo de saída do Cordial, quando aberto em um editor de texto, exibe três coluna distintas. Uma para as palavras, outra para etiquetas morfosintáticas e outra para os lemas. Um exemplo pode ser visto na página "Resultados".
O TreeTagger é um software gratuíto desenvolvido por Helmut Schmid e está disponível para download nestelink. Ele pode ser utilizado para etiquetar textos em Alemão, Inglês, Francês, Italiano, Espanhol, Búlgaro, Russo, Português, Galiciano, Chinês, Suaília, Eslovaco, Latim, Estoniano, Polonês e Francês antigo.
Cordial é um software pago que possui muitas ferramentas para o tratamento linguístico como um dicionário e um tradutor. Ele possui muitas funcionlidades, porém é mais limitado em termos de línguas suportadas para etiquetagem morfosintática. Em geral, nós achamos que os resultados são mais precisos do que aqueles pelo TreeTagger. Você pode ler mais sobre o Cordial neste link.
O método do professor
Esta versão encadra perfeitamente na categoria "Puro Perl", já que ela utiliza um módulo (Unicode::String) para converter os arquivos utf-8. Trata-se de uma versão vista em aula que nós tentamos melhorar disponível nas páginas "Nossos Resultados".
- #/usr/bin/perl
- use Unicode::String qw(utf8);
- #-----------------------------------------------------------
- my $rep="$ARGV[0]";
- # on s'assure que le nom du répertoire ne se termine pas par un "/"
- $rep=~ s/[\/]$//;
- # on initialise une variable contenant le flux de sortie
- my %dictionnairedesitems=();
- my %dictionnairesdesrubriques=();
- #----------------------------------------
- &parcoursarborescencefichierspourrepererlesrubriques($rep); # on recupere les rubriques...
- #----------------------------------------
- my @liste_rubriques = keys(%dictionnairesdesrubriques);
- foreach my $rub (@liste_rubriques) {
- print $rub,"\n";
- #----------------------------------------
- my $output1="SORTIE/SORTIE-extract-txt-".$rub.".xml";
- my $output2="SORTIE/SORTIE-extract-txt-".$rub.".txt";
- my $output3="SORTIE/SORTIE-extract-txt-".$rub."-treetagger.xml";
- if (!open (FILEOUT1,">:encoding(utf-8)", $output1)) { die "Pb a l'ouverture du fichier $output1"};
- if (!open (FILEOUT2,">:encoding(utf-8)",$output2)) { die "Pb a l'ouverture du fichier $output2"};
- if (!open (FILEOUT3,">:encoding(utf-8)",$output3)) { die "Pb a l'ouverture du fichier $output3"};
- print FILEOUT1 "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
- print FILEOUT1 "<PARCOURS>\n";
- print FILEOUT3 "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
- print FILEOUT3 "<PARCOURS>\n";
- close(FILEOUT1);
- close(FILEOUT2);
- close(FILEOUT3);
- }
- #----------------------------------------
- &parcoursarborescencefichiers($rep); # on traite tous les fichiers
- #----------------------------------------
- foreach my $rub (@liste_rubriques) {
- my $output1="SORTIE/SORTIE-extract-txt-".$rub.".xml";
- my $output3="SORTIE/SORTIE-extract-txt-".$rub."-treetagger.xml";
- if (!open (FILEOUT1,">>:encoding(utf-8)", $output1)) { die "Pb a l'ouverture du fichier $output1"};
- if (!open (FILEOUT3,">>:encoding(utf-8)",$output3)) { die "Pb a l'ouverture du fichier $output3"};
- print FILEOUT1 "</PARCOURS>\n";
- print FILEOUT3 "</PARCOURS>\n";
- close(FILEOUT1);
- close(FILEOUT3);
- }
- exit;
- #----------------------------------------------
- #----------------------------------------------
- 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); #recurse!
- }
- if (-f $file) {
- if (($file=~/\.xml$/) && ($file!~/\/fil.+\.xml$/)) {
- open(FILE, $file);
- #print "Traitement de :\n$file\n";
- my $texte="";
- while (my $ligne=<FILE>) {
- $ligne =~ s/\n//g;
- $texte .= $ligne;
- }
- close(FILE);
- $texte=~/encoding ?= ?[\'\"]([^\'\"]+)[\'\"]/i;
- my $encodage=$1;
- #print "ENCODAGE : $encodage \n";
- if ($encodage ne "") {
- print "Extraction dans : $file \n";
- my $tmptexteXML="<file>\n";
- $tmptexteXML.="<name>$file</name>\n";
- my $tmptexteXMLtagger="<file>\n";
- $tmptexteXMLtagger.="<name>$file</name>\n";
- $texte =~ s/> *</></g;
- $texte=~/<pubDate>([^<]+)<\/pubDate>/;
- $tmptexteXML.="<date>$1</date>\n";
- $tmptexteXML.="<items>\n";
- $tmptexteXMLtagger.="<date>$1</date>\n";
- $tmptexteXMLtagger.="<items>\n";
- my $tmptexteBRUT="";
- open(FILE,"<:encoding($encodage)", $file);
- #print "Traitement de :\n$file\n";
- $texte="";
- while (my $ligne=<FILE>) {
- $ligne =~ s/\n//g;
- $texte .= $ligne;
- }
- close(FILE);
- $texte=~s/> *</></g;
- # on recherche la rubrique
- $texte=~/<channel><title>([^<]+)<\/title>/;
- my $rub=$1;
- $rub=~s/é/e/gi;
- $rub=~s/è/e/gi;
- $rub=~s/ê/e/gi;
- $rub=~s/à/a/gi;
- $rub=~ s/Le *Monde *\. *fr *://gi;
- $rub=~ s/ //g;
- $rub=~ s/s$//;
- $rub=uc($rub);
- #print $rub,"\n";
- #----------------------------------------
- my $output1="SORTIE/SORTIE-extract-txt-".$rub.".xml";
- my $output2="SORTIE/SORTIE-extract-txt-".$rub.".txt";
- my $output3="SORTIE/SORTIE-extract-txt-".$rub."-treetagger.xml";
- if (!open (FILEOUT1,">>:encoding(utf-8)", $output1)) { die "Pb a l'ouverture du fichier $output1"};
- if (!open (FILEOUT2,">>:encoding(utf-8)", $output2)) { die "Pb a l'ouverture du fichier $output2"};
- if (!open (FILEOUT3,">>:encoding(utf-8)", $output3)) { die "Pb a l'ouverture du fichier $output3"};
- #----------------------------------------
- my $compteurItem=0;
- my $compteurEtiquetage=0;
- while ($texte =~ /<item><title>(.+?)<\/title>.+?<description>(.+?)<\/description>/g) {
- my $titre=$1;
- my $resume=$2;
- #print "T : $titre \n R : $resume \n";
- if (uc($encodage) ne "UTF-8") {utf8($titre);utf8($resume);}
- $titre = &nettoietexte($1);
- $resume = &nettoietexte($2);
- $compteurItem++;
- if (!(exists($dictionnairedesitems{$resume}))) {
- $compteurEtiquetage++;
- print "Etiquetage (num : $compteurEtiquetage) sur item (num : $compteurItem) \n";
- my ($titreetiquete,$texteetiquete)=&etiquetageavectreetagger($titre,$resume);
- $tmptexteBRUT.="§ $titre \n";
- $tmptexteBRUT.="$resume \n";
- $tmptexteXML.="<item><title>$titre</title><abstract>$resume</abstract></item>\n";
- $tmptexteXMLtagger.="<item>\n<title>\n$titreetiquete</title>\n<abstract>\n$texteetiquete</abstract>\n</item>\n";
- $dictionnairedesitems{$resume}++;
- }
- else {
- $tmptexteXML.="<item><title>-</title><abstract>-</abstract></item>\n";
- }
- }
- $tmptexteXML.="</items>\n</file>\n";
- $tmptexteXMLtagger.="</items>\n</file>\n";
- print FILEOUT1 $tmptexteXML;
- print FILEOUT2 $tmptexteBRUT;
- print FILEOUT3 $tmptexteXMLtagger;
- close FILEOUT1;
- close FILEOUT2;
- close FILEOUT3;
- }
- else {
- print "$file ==> $encodage \n";
- }
- }
- }
- }
- }
- #----------------------------------------------------
- sub nettoietexte {
- my $texte=shift;
- $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;
- $texte=~s/'/'/g;
- $texte=~s/"/"/g;
- $texte=~s/&#39;/'/g;
- $texte=~s/&#34;/"/g;
- return $texte;
- }
- #-----------------------------------------------------------------------------------
- sub parcoursarborescencefichierspourrepererlesrubriques {
- 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) {
- &parcoursarborescencefichierspourrepererlesrubriques($file); #recurse!
- }
- if (-f $file) {
- if (($file=~/\.xml$/) && ($file!~/\/fil.+\.xml$/)) {
- open(FILE,$file);
- #print "Traitement de :\n$file\n";
- my $texte="";
- while (my $ligne=<FILE>) {
- $ligne =~ s/\n//g;
- $texte .= $ligne;
- }
- close(FILE);
- $texte=~/encoding ?= ?[\'\"]([^\'\"]+)[\'\"]/i;
- my $encodage=$1;
- if ($encodage ne "") {
- open(FILE,"<:encoding($encodage)", $file);
- #print "Traitement de :\n$file\n";
- $texte="";
- while (my $ligne=<FILE>) {
- $ligne =~ s/\n//g;
- $texte .= $ligne;
- }
- close(FILE);
- $texte =~ s/> *</></g;
- if ($texte=~ /<channel><title>([^>]+)<\/title>/) {
- my $rub=$1;
- $rub=~s/é/e/gi;
- $rub=~s/è/e/gi;
- $rub=~s/ê/e/gi;
- $rub=~s/à/a/gi;
- $rub=~ s/Le *Monde *\. *fr *://gi;
- $rub=~ s/ //g;
- $rub=~ s/s$//;
- $rub=uc($rub);
- $dictionnairesdesrubriques{$rub}++;
- }
- }
- else {
- #print "$file ==> $encodage \n";
- }
- }
- }
- }
- }
- sub etiquetageavectreetagger {
- 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);
- }
#/usr/bin/perl use Unicode::String qw(utf8); #----------------------------------------------------------- my $rep="$ARGV[0]"; # on s'assure que le nom du répertoire ne se termine pas par un "/" $rep=~ s/[\/]$//; # on initialise une variable contenant le flux de sortie my %dictionnairedesitems=(); my %dictionnairesdesrubriques=(); #---------------------------------------- &parcoursarborescencefichierspourrepererlesrubriques($rep); # on recupere les rubriques... #---------------------------------------- my @liste_rubriques = keys(%dictionnairesdesrubriques); foreach my $rub (@liste_rubriques) { print $rub,"\n"; #---------------------------------------- my $output1="SORTIE/SORTIE-extract-txt-".$rub.".xml"; my $output2="SORTIE/SORTIE-extract-txt-".$rub.".txt"; my $output3="SORTIE/SORTIE-extract-txt-".$rub."-treetagger.xml"; if (!open (FILEOUT1,">:encoding(utf-8)", $output1)) { die "Pb a l'ouverture du fichier $output1"}; if (!open (FILEOUT2,">:encoding(utf-8)",$output2)) { die "Pb a l'ouverture du fichier $output2"}; if (!open (FILEOUT3,">:encoding(utf-8)",$output3)) { die "Pb a l'ouverture du fichier $output3"}; print FILEOUT1 "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"; print FILEOUT1 "<PARCOURS>\n"; print FILEOUT3 "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"; print FILEOUT3 "<PARCOURS>\n"; close(FILEOUT1); close(FILEOUT2); close(FILEOUT3); } #---------------------------------------- &parcoursarborescencefichiers($rep); # on traite tous les fichiers #---------------------------------------- foreach my $rub (@liste_rubriques) { my $output1="SORTIE/SORTIE-extract-txt-".$rub.".xml"; my $output3="SORTIE/SORTIE-extract-txt-".$rub."-treetagger.xml"; if (!open (FILEOUT1,">>:encoding(utf-8)", $output1)) { die "Pb a l'ouverture du fichier $output1"}; if (!open (FILEOUT3,">>:encoding(utf-8)",$output3)) { die "Pb a l'ouverture du fichier $output3"}; print FILEOUT1 "</PARCOURS>\n"; print FILEOUT3 "</PARCOURS>\n"; close(FILEOUT1); close(FILEOUT3); } exit; #---------------------------------------------- #---------------------------------------------- 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); #recurse! } if (-f $file) { if (($file=~/\.xml$/) && ($file!~/\/fil.+\.xml$/)) { open(FILE, $file); #print "Traitement de :\n$file\n"; my $texte=""; while (my $ligne=<FILE>) { $ligne =~ s/\n//g; $texte .= $ligne; } close(FILE); $texte=~/encoding ?= ?[\'\"]([^\'\"]+)[\'\"]/i; my $encodage=$1; #print "ENCODAGE : $encodage \n"; if ($encodage ne "") { print "Extraction dans : $file \n"; my $tmptexteXML="<file>\n"; $tmptexteXML.="<name>$file</name>\n"; my $tmptexteXMLtagger="<file>\n"; $tmptexteXMLtagger.="<name>$file</name>\n"; $texte =~ s/> *</></g; $texte=~/<pubDate>([^<]+)<\/pubDate>/; $tmptexteXML.="<date>$1</date>\n"; $tmptexteXML.="<items>\n"; $tmptexteXMLtagger.="<date>$1</date>\n"; $tmptexteXMLtagger.="<items>\n"; my $tmptexteBRUT=""; open(FILE,"<:encoding($encodage)", $file); #print "Traitement de :\n$file\n"; $texte=""; while (my $ligne=<FILE>) { $ligne =~ s/\n//g; $texte .= $ligne; } close(FILE); $texte=~s/> *</></g; # on recherche la rubrique $texte=~/<channel><title>([^<]+)<\/title>/; my $rub=$1; $rub=~s/é/e/gi; $rub=~s/è/e/gi; $rub=~s/ê/e/gi; $rub=~s/à/a/gi; $rub=~ s/Le *Monde *\. *fr *://gi; $rub=~ s/ //g; $rub=~ s/s$//; $rub=uc($rub); #print $rub,"\n"; #---------------------------------------- my $output1="SORTIE/SORTIE-extract-txt-".$rub.".xml"; my $output2="SORTIE/SORTIE-extract-txt-".$rub.".txt"; my $output3="SORTIE/SORTIE-extract-txt-".$rub."-treetagger.xml"; if (!open (FILEOUT1,">>:encoding(utf-8)", $output1)) { die "Pb a l'ouverture du fichier $output1"}; if (!open (FILEOUT2,">>:encoding(utf-8)", $output2)) { die "Pb a l'ouverture du fichier $output2"}; if (!open (FILEOUT3,">>:encoding(utf-8)", $output3)) { die "Pb a l'ouverture du fichier $output3"}; #---------------------------------------- my $compteurItem=0; my $compteurEtiquetage=0; while ($texte =~ /<item><title>(.+?)<\/title>.+?<description>(.+?)<\/description>/g) { my $titre=$1; my $resume=$2; #print "T : $titre \n R : $resume \n"; if (uc($encodage) ne "UTF-8") {utf8($titre);utf8($resume);} $titre = &nettoietexte($1); $resume = &nettoietexte($2); $compteurItem++; if (!(exists($dictionnairedesitems{$resume}))) { $compteurEtiquetage++; print "Etiquetage (num : $compteurEtiquetage) sur item (num : $compteurItem) \n"; my ($titreetiquete,$texteetiquete)=&etiquetageavectreetagger($titre,$resume); $tmptexteBRUT.="§ $titre \n"; $tmptexteBRUT.="$resume \n"; $tmptexteXML.="<item><title>$titre</title><abstract>$resume</abstract></item>\n"; $tmptexteXMLtagger.="<item>\n<title>\n$titreetiquete</title>\n<abstract>\n$texteetiquete</abstract>\n</item>\n"; $dictionnairedesitems{$resume}++; } else { $tmptexteXML.="<item><title>-</title><abstract>-</abstract></item>\n"; } } $tmptexteXML.="</items>\n</file>\n"; $tmptexteXMLtagger.="</items>\n</file>\n"; print FILEOUT1 $tmptexteXML; print FILEOUT2 $tmptexteBRUT; print FILEOUT3 $tmptexteXMLtagger; close FILEOUT1; close FILEOUT2; close FILEOUT3; } else { print "$file ==> $encodage \n"; } } } } } #---------------------------------------------------- sub nettoietexte { my $texte=shift; $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; $texte=~s/'/'/g; $texte=~s/"/"/g; $texte=~s/&#39;/'/g; $texte=~s/&#34;/"/g; return $texte; } #----------------------------------------------------------------------------------- sub parcoursarborescencefichierspourrepererlesrubriques { 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) { &parcoursarborescencefichierspourrepererlesrubriques($file); #recurse! } if (-f $file) { if (($file=~/\.xml$/) && ($file!~/\/fil.+\.xml$/)) { open(FILE,$file); #print "Traitement de :\n$file\n"; my $texte=""; while (my $ligne=<FILE>) { $ligne =~ s/\n//g; $texte .= $ligne; } close(FILE); $texte=~/encoding ?= ?[\'\"]([^\'\"]+)[\'\"]/i; my $encodage=$1; if ($encodage ne "") { open(FILE,"<:encoding($encodage)", $file); #print "Traitement de :\n$file\n"; $texte=""; while (my $ligne=<FILE>) { $ligne =~ s/\n//g; $texte .= $ligne; } close(FILE); $texte =~ s/> *</></g; if ($texte=~ /<channel><title>([^>]+)<\/title>/) { my $rub=$1; $rub=~s/é/e/gi; $rub=~s/è/e/gi; $rub=~s/ê/e/gi; $rub=~s/à/a/gi; $rub=~ s/Le *Monde *\. *fr *://gi; $rub=~ s/ //g; $rub=~ s/s$//; $rub=uc($rub); $dictionnairesdesrubriques{$rub}++; } } else { #print "$file ==> $encodage \n"; } } } } } sub etiquetageavectreetagger { 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); }
Ferramenta 2 & Ferramenta 3 & Ferramenta 4
Uma parte bonus desta seção tratava-ze de utilizar o programa Le Trameur para etiquetar o texto utilizando a função imbutida TreeTagger, extrair sequências morfosintáticas para em seguida visualizar os resultados em uma série de gráficos. De uma maneira geral, o programa é capaz de substituir as Ferramentas 2, 3, e 4.
Caso você não utilize Windows, ainda assim existe um meio de utilizar Le Trameur. Trata-se do (Wine). No entanto, algumas funcionalidades não estão disponíveis na utilizaçao do Le Trameur com o Wine. TreeTagger, por exemplo, é uma das funções que não pode ser realizada bônus, utilizando Wine.
Uma descrição completa das funões do Le Trameur podem ser encontradas nesta página.
Puro Perl
Como nós já indicamos anteriormente, nossa versão Puro Perl consiste em não utilizar módulos Perl no nosso programa. Nós desenvolvemos nós mesmos todas as funções necessárias ao bom funcionamento do script.
Para os tratamento das entidades; nós criamos uma função que as modifica por caracteres equivalentes. Nós tivemos que enumerá-las uma a uma afim de obtermos a lista mais completa possível. Essa função se chama "nettoyerTexte". Nós realizamos também uma outra limpeza para os temas. Porém, neste caso não se trata de entidades, mas de caracteres acentuados que nós substituímos por caracteres não acentuadso de modo a obter nomes de arquivos sem acentos, sinais de pontuação ou URL.
Para a criação dos nossos arquivos de resultados, nós não utilizamos o módulo XML::RSS. As saídas XML e TXT foram criadas por nós mesmos.
Ao contrário da versão feita em aula, nós criamos um repertório de saída que é subdivido em dois repertórios; um reúne os arquivos etiquetados por TreeTagger e o outro, os títulos e as descrição em arquivo TXT. Para isso nós utilizamos a recursividade da função "parcoursarborescencefichiers", afim de recuperar os desejados.
- #!/usr/bin/perl
- <<DOC;
- Votre Nom : Bienvenue, Poadey, Cavalcante
- MARS 2015
- usage : perl parcours-arborescence-fichiers repertoire-a-parcourir
- Le programme prend en entrée le nom du répertoire contenant les fichiers
- à traiter
- Le programme construit en sortie des fichiers structurés : en format XML
- et en format TXT
- DOC
- use Unicode::String qw(utf8);
- use utf8;
- # pour pouvoir afficher la date
- use Time::localtime;
- #------------------------------------------------------------------------------
- # des compteurs pour le nombre des items
- my $nb_filesIN = 0;
- my $nb_itemsIN = 0;
- my $nb_itemsOUT = 0;
- #------------------------------------------------------------------------------
- # le répertoire d'entrée
- my $rep = "$ARGV[0]";
- # enlever le slash à la fin du répertoire
- $rep =~ s/[\/]$//;
- #------------------------------------------------------------------------------
- # des hash tables pour vérifier qu'on n'a pas deux fois les même infos
- my %dico_titre = ();
- my %dico_description = ();
- # cet hash nous permet de juste traiter une fois chaque texte
- my %dico_files = ();
- # creer l`objet date pour ecrire les dates dans le log
- my $date_time = ctime();
- #------------------------------------------------------------------------------
- # creation des dossiers de sortie
- my $res = "./Sorties/";
- if (! -e $res) {
- mkdir($res) or die ("Problème avec la création du répertoire de $rep : $!");
- }
- $res = "./Sorties/Sorties_PurePerl/";
- if (! -e $res) {
- mkdir($res) or die ("Problème avec la création du répertoire de $rep : $!\n");
- }
- #------------------------------------------------------------------------------
- # sorties etiquetées
- my $resBAO2 = "./Sorties/Sorties_Tagged/";
- if (! -e $resBAO2) {
- mkdir($resBAO2) or die ("Problème avec la création du répertoire de $rep : $!\n");
- }
- #------------------------------------------------------------------------------
- # sortie globale txt
- open(FILEGLOBALTXT,">:encoding(UTF-8)", $res."SortieGlobale1.txt");
- #------------------------------------------------------------------------------
- &parcoursarborescencefichiers($rep); #recurse!
- #------------------------------------------------------------------------------
- close FILEGLOBALTXT;
- #------------------------------------------------------------------------------
- # création de la sortie globale xml
- open(FILEGLOBALXML, ">:encoding(UTF-8)", $res."SortieGlobale1.xml");
- print FILEGLOBALXML "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
- print FILEGLOBALXML "<PARCOURS>\n";
- print FILEGLOBALXML "<NOM>Bienvenue, Poadey, Cavalcante</NOM>\n";
- print FILEGLOBALXML "<FILTRAGE>";
- #------------------------------------------------------------------------------
- # écrire contenu de la sortie globale xml
- opendir(DIR, $res) or die "Erreur d'ouverture du repertoire: $!\n";
- my @sorties = readdir(DIR);
- closedir(DIR);
- foreach my $sortie (@sorties) {
- if ($sortie=~/(.+?)\.xml$/ && $1 != "SortieGlobale1") {
- my $rub=$1;
- open(FILE,">>:encoding(UTF-8)", $res.$sortie);
- print FILE "</".$rub.">\n";;
- print FILE "</PARCOURS>\n";
- close(FILE);
- print FILEGLOBALXML "<$rub>\n";
- print FILEGLOBALXML ${"DumpXML".$rub};
- print FILEGLOBALXML "</$rub>";
- }
- }
- print FILEGLOBALXML "</FILTRAGE>\n";
- print FILEGLOBALXML "</PARCOURS>\n";
- close(FILEGLOBALXML);
- #------------------------------------------------------------------------------
- open(FILEGLOBALXML, ">:encoding(UTF-8)", $resBAO2."SortieGlobale2.xml");
- print FILEGLOBALXML "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
- print FILEGLOBALXML "<PARCOURS>\n";
- print FILEGLOBALXML "<NOM>Bienvenue, Poadey, Cavalcante</NOM>\n";
- print FILEGLOBALXML "<FILTRAGE>";
- #------------------------------------------------------------------------------
- opendir(DIR, $resBAO2) or die "Erreur d'ouverture de repertoire: $!\n";
- @sorties = readdir(DIR);
- closedir(DIR);
- foreach my $sortie (@sorties) {
- # se fait sur chaque sortie xml dans chaque rubrique
- if ($sortie=~/(.+?)\.xml$/ && $1 != "SortieGlobale2") {
- my $rub = $1;
- open(FILE,">>:encoding(UTF-8)", $resBAO2.$sortie);
- print FILE "</".$rub.">\n";;
- print FILE "</PARCOURS>\n";
- close FILE;
- print FILEGLOBALXML "<$rub>\n";
- print FILEGLOBALXML ${"DumpXML2_Tagged".$rub};
- print FILEGLOBALXML "</$rub>";
- }
- }
- #------------------------------------------------------------------------------
- print FILEGLOBALXML "</FILTRAGE>\n";
- print FILEGLOBALXML "</PARCOURS>\n";
- close(FILEGLOBALXML);
- #------------------------------------------------------------------------------
- # imprime le nombre des infos à la fin du programme
- print "\n" . "files IN = $nb_filesIN\n";
- print "items IN = $nb_itemsIN\n";
- print "items OUT = $nb_itemsOUT\n";
- print "fin.\n";
- exit;
- # fin du main programme
- #------------------------------------------------------------------------------
- #------------------------------------------------------------------------------
- # commencement des subroutines
- #------------------------------------------------------------------------------
- # subroutine pour parcourir l'aborescence
- sub parcoursarborescencefichiers {
- my $path = shift(@_); # chemin vers le dossier en entrée
- opendir(DIR, $path) or die "Probleme d'ouverture du dossier: $!\n";
- my @files = readdir(DIR);
- closedir(DIR);
- #--------------------------------------------
- foreach my $file (@files) {
- next if $file =~ /^\.\.?$/; #si . ou ..
- $file = $path."/".$file;
- #si $file est un dossier
- if (-d $file) {
- &parcoursarborescencefichiers($file); #recurse!
- }
- # faire le traitement si $file est un fichier
- if (-f $file) {
- # traiter les fichiers xml seulement
- if ($file=~/^[^(fil)]+?\.xml$/) {
- $nb_filesIN++;
- print $file,"\n";
- #lire le fichier xml
- open(FILE,$file);
- my $firstLine = <FILE>;
- my $encodage = "";
- #vérifier encodage du fichier xml
- if($firstLine =~ /encoding= ?['"]([^\'"]+)['"]/) {
- $encodage = $1; #extraire l'encodage
- }
- close(FILE);
- # si on trouve l'encodage, le fichier est reouvert avec l'encodage correcte
- if (!($encodage eq "")) {
- open(FILE,"<:encoding($encodage)",$file);
- my $texte = "";
- #éliminer les retours à ligne dans le fichier [ \n et \r ]
- while (my $ligne = <FILE>) {
- $ligne =~ s/\n//g;
- $ligne =~ s/\r//g;
- $texte .= $ligne;
- }
- close FILE;
- $texte =~ s/> *?</></g; # coller les balises
- #-----------------------------------------
- # extraire rubrique, date et nom
- $texte =~ /<channel>.*?<title>(.*?)<\/title>.*?<pubDate>(.+?)<\/pubDate>.*?<\/channel>/;
- # nettoyer les rubriques
- my $rubrique = &nettoyerRubriques($1);
- print "RUBRIQUE : $rubrique\n";
- # extraire la date
- my $date = &nettoyerRubriques($2);
- # nom du fichier
- my $name = $file;
- # uniquement les fichiers XML contenant les mises à jour
- $name =~ s/.*?(20.*)/$1/;
- #------------------------------------------
- # ouvre des balises et écrire dans des fichiers de sortie
- my $cheminXML=$res.$rubrique.".xml";
- # si on n'a pas encore vu le rubrique on doit le créer
- if (! -e $cheminXML) {
- # créer un fichier
- if (!open (FILEOUT,">:encoding(UTF-8)",$cheminXML)) {
- die "Probleme a la creation du fichier $cheminXML : $!";
- }
- # ouverture des balises XML du début du fichier
- print FILEOUT "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
- print FILEOUT "<PARCOURS>\n";
- print FILEOUT "<NOM>Bienvenue, Poadey, Cavalcante</NOM>\n";
- print FILEOUT "<$rubrique>\n";
- print FILEOUT "<file>";
- print FILEOUT "<name>$name</name>";
- print FILEOUT "<date>$date</date>";
- print FILEOUT "<items>";
- close(FILEOUT);
- ${"DumpXML"."$rubrique"}="";
- }
- # si le fichier existe déjà
- else {
- if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML)) {
- die "Problème a l'ouverture du fichier $cheminXML : $!\n";
- }
- print FILEOUT "<file>";
- print FILEOUT "<name>$name</name>";
- print FILEOUT "<date>$date</date>";
- print FILEOUT "<items>";
- close(FILEOUT);
- }
- #-------------------------------------------
- my $cheminXML_BAO2=$resBAO2.$rubrique.".xml";
- # si on n'a pas encore vu le rubrique
- if (! -e $cheminXML_BAO2) {
- # créer un fichier
- if (!open (FILEOUT,">:encoding(UTF-8)",$cheminXML_BAO2)) {
- die "Probleme a la creation du fichier $cheminXML_BAO2 : $!\n";
- }
- # ouverture des balises XML du début du fichier
- print FILEOUT "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
- print FILEOUT "<PARCOURS>\n";
- print FILEOUT "<NOM>Bienvenue, Poadey, Cavalcante</NOM>\n";
- print FILEOUT "<$rubrique>\n";
- print FILEOUT "<file>";
- print FILEOUT "<name>$name</name>";
- print FILEOUT "<date>$date</date>";
- print FILEOUT "<items>";
- close(FILEOUT);
- ${"DumpXML_tagged"."$rubrique"}="";
- }
- # si le fichier existe déjà
- else {
- if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML_BAO2)) {
- die "Problème a l'ouverture du fichier $cheminXML_BAO2 : $!\n";
- }
- print FILEOUT "<file>";
- print FILEOUT "<name>$file</name>";
- print FILEOUT "<date>$date</date>";
- print FILEOUT "<items>";
- close(FILEOUT);
- }
- #---------------------------------------------
- # extractions des titres et descriptions
- while ($texte =~ /<item>.*?<title>(.*?)<\/title>.*?<description>(.*?)<\/description>/g)
- {
- my $titre = $1;
- my $description = $2;
- $nb_itemsIN++;
- #-----------------------------------------
- # nettoyer le texte
- $titre = &nettoyerTexte($titre);
- $description = &nettoyerTexte($description);
- if (!(($titre eq "") or ($description eq ""))) {
- #-----------------------------------------
- # convertir si besoin en utf-8
- if (uc($encodage) ne "UTF-8") {
- utf8($titre);
- utf8($description);
- }
- #----------------------------------------------
- # regarde si on a déjà vu le texte
- if (!((exists $dico_titre{$rubrique . $titre}) && (exists $dico_description{$rubrique . $description})))
- {
- $dico_titre{$rubrique . $titre} = "1";
- $dico_description{$rubrique . $description} = "1";
- $nb_itemsOUT++;
- #------------------------------------------
- # faire l'etiquetage
- my $titre_tagged = &treetagger($titre);
- my $description_tagged = &treetagger($description);
- open(LOG, ">>", "log_bao2.txt");
- if(exists $dico_files{$file}){
- $count_file = int($dico_files{$file});
- $count_file++;
- %dico_files = ($file => $count_file);
- } else {
- %dico_files = ($file => 1);
- }
- #creer l`objet date pour ecrire les dates dans le log
- my $date_time = ctime();
- #ecrire le fichier de log avec le nom du fichier et l`heure de lecture
- print LOG $file." ".$dico_files{$file}."\t\t read on ".$date_time."\n";
- # mettre dans les sorties xml
- if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML)) {
- die "Problème a l'ouverture du fichier $cheminXML : $!\n";
- }
- print FILEOUT "<item>\n";
- print FILEOUT "<titre>" . $titre . "</titre>\n<description>" . $description . "</description>\n";
- print FILEOUT "</item>\n";
- close(FILEOUT);
- #----------------------------------------------
- # créer un dump pour chaque rubrique
- ${"DumpXML" . $rubrique} .= "<item>\n<titre>" . $titre . "</titre>\n<description>" . $description . "</description>\n</item>\n";
- #----------------------------------------------
- # partie de sorties txt
- my $cheminTXT = $res . $rubrique . ".txt";
- # si on n'a pas encore vu la rubrique
- if (! -e $cheminTXT) {
- if (!open (FILEGLOBALTXT,">>:encoding(iso-8859-15)",$cheminTXT)) {
- die "Problème a l'ouverture du fichier $cheminTXT : $!\n";
- }
- # écrire dans le sortie txt
- print FILEGLOBALTXT "$titre." . " $description.\n";
- close(FILEGLOBALTXT);
- }
- # si on a déjà vu la rubrique
- else {
- if (!open (FILEGLOBALTXT,">>:encoding(iso-8859-15)",$cheminTXT)) {
- die "Problème a l'ouverture du fichier $cheminTXT : $!\n";
- }
- # écrire dans le sortie txt
- print FILEGLOBALTXT "$titre." . " $description.";
- close(FILEGLOBALTXT);
- }
- if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML_BAO2)) {
- die "Problème a l'ouverture du fichier $cheminXML_BAO2 : $!\n";
- }
- print FILEOUT "<item>\n";
- print FILEOUT "<titre>".$titre_tagged."</titre>\n<description>".$description_tagged."</description>\n";
- print FILEOUT "</item>\n";
- close(FILEOUT);
- # créer un dump pour chaque rubrique
- ${"DumpXML2_Tagged".$rubrique}.="<item>\n<titre>".$titre_tagged."</titre>\n<description>".$description_tagged."</description>\n</item>\n";
- }
- }
- }
- # fermer la balise file pour chaque fichier xml
- if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML))
- {
- die "Problème a l'ouverture du fichier .$cheminXML : $!\n";
- }
- print FILEOUT "</items>";
- print FILEOUT "</file>";
- close(FILEOUT);
- # fermer la balise les fichier xml etiqutée
- if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML_BAO2)) {
- die "Problème a l'ouverture du fichier .$cheminXML_BAO2 : $!\n";
- }
- print FILEOUT "</items>";
- print FILEOUT "</file>";
- close(FILEOUT);
- }
- }
- }
- }
- }
- #------------------------------------------------------------------------------
- # subroutine pour nettoyer le texte
- #------------------------------------------------------------------------------
- sub nettoyerTexte {
- my $tx = $_[0];
- $tx =~ s/&/&/g;
- $tx =~ s/&/&/g;
- $tx =~ s/"/"/g;
- $tx =~ s/"/"/g;
- $tx =~ s/'/'/g;
- $tx =~ s/'/'/g;
- $tx =~ s/</</g;
- $tx =~ s/</</g;
- $tx =~ s/>/>/g;
- $tx =~ s/>/>/g;
- $tx =~ s/ //g;
- $tx =~ s/ //g;
- $tx =~ s/£/£/g;
- $tx =~ s/£/£/g;
- $tx =~ s/©/©/g;
- $tx =~ s/«/«/g;
- $tx =~ s/«/«/g;
- $tx =~ s/»/»/g;
- $tx =~ s/»//g;
- $tx =~ s/É/É/g;
- $tx =~ s/É/É/g;
- $tx =~ s/í/î/g;
- $tx =~ s/î/î/g;
- $tx =~ s/ï/ï/g;
- $tx =~ s/ï/ï/g;
- $tx =~ s/à/à/g;
- $tx =~ s/à/à/g;
- $tx =~ s/â/â/g;
- $tx =~ s/â/â/g;
- $tx =~ s/ç/ç/g;
- $tx =~ s/ç/ç/g;
- $tx =~ s/è/è/g;
- $tx =~ s/è/è/g;
- $tx =~ s/é/é/g;
- $tx =~ s/é/é/g;
- $tx =~ s/ê/ê/g;
- $tx =~ s/ê/ê/g;
- $tx =~ s/ô/ô/g;
- $tx =~ s/ô/ô/g;
- $tx =~ s/û/û/g;
- $tx =~ s/û/û/g;
- $tx =~ s/ü/ü/g;
- $tx =~ s/ü/ü/g;
- $tx =~ s/\x9c/œ/g;
- $tx =~ s/<br\/\>//g;
- $tx =~ s/<img.*?\/>//g;
- $tx =~ s/<.+?>//sg;
- $tx =~ s/<a.*?>.*?<\/a>//g;
- $tx =~ s/<![CDATA[(.*?)]]>/$1/g;
- $tx =~ s/<[^>]>//g;
- $tx =~ s/\.$//;
- $tx =~ s/&/et/g;
- return $tx;
- }
- #------------------------------------------------------------------------------
- # subroutine pour nettoyer des rubriques
- #------------------------------------------------------------------------------
- sub nettoyerRubriques {
- my $rubrique = shift;
- $rubrique =~ s/Le Monde.fr//g;
- $rubrique =~ s/LeMonde.fr//g;
- $rubrique =~ s/: Toute l'actualité sur//g;
- $rubrique =~ s/É/e/g;
- $rubrique =~ s/é/e/g;
- $rubrique =~ s/è/e/g;
- $rubrique =~ s/ê/a/g;
- $rubrique =~ s/ë/e/g;
- $rubrique =~ s/ï/i/g;
- $rubrique =~ s/î/i/g;
- $rubrique =~ s/à/a/g;
- $rubrique =~ s/ô/o/g;
- $rubrique =~ s/,/_/g;
- $rubrique = uc($rubrique);
- $rubrique =~ s/ //g;
- $rubrique =~ s/[\.\:;\'\"\-]+//g;
- return $rubrique;
- }
- #------------------------------------------------------------------------------
- # subroutine pour le tokenisation et etiquetage
- #------------------------------------------------------------------------------
- sub treetagger {
- my $texte = shift;
- my $temptag;
- # créer un fichier temporaire pour tagger des morceaux de texte
- open($temptag, ">:encoding(UTF-8)", "./temptag.txt");
- print $temptag $texte;
- close($temptag);
- system("perl tokenise-utf8.pl ./temptag.txt | /home/alexandre/tree-tagger/bin/tree-tagger -lemma -token -no-unknown -sgml /home/alexandre/tree-tagger/models/french.par > treetagger.txt");
- system("perl ./treetagger2xml-utf8.pl treetagger.txt utf-8");
- open(TaggedOUT,"<:encoding(utf-8)","treetagger.txt.xml");
- my $tagged_text = "";
- #lire la ligne d'en tête du fichier xml étiqueté, pour éviter que cette
- # ligne soit inclue dans le nouveau fichier xml
- my $line_den_tete = <TaggedOUT>;
- while (my $l = <TaggedOUT>) {
- $tagged_text .= $l;
- }
- close(TaggedOUT);
- return $tagged_text;
- }
- # fin des subroutines
- #------------------------------------------------------------------------------
- #------------------------------------------------------------------------------
#!/usr/bin/perl <<DOC; Votre Nom : Bienvenue, Poadey, Cavalcante MARS 2015 usage : perl parcours-arborescence-fichiers repertoire-a-parcourir Le programme prend en entrée le nom du répertoire contenant les fichiers à traiter Le programme construit en sortie des fichiers structurés : en format XML et en format TXT DOC use Unicode::String qw(utf8); use utf8; # pour pouvoir afficher la date use Time::localtime; #------------------------------------------------------------------------------ # des compteurs pour le nombre des items my $nb_filesIN = 0; my $nb_itemsIN = 0; my $nb_itemsOUT = 0; #------------------------------------------------------------------------------ # le répertoire d'entrée my $rep = "$ARGV[0]"; # enlever le slash à la fin du répertoire $rep =~ s/[\/]$//; #------------------------------------------------------------------------------ # des hash tables pour vérifier qu'on n'a pas deux fois les même infos my %dico_titre = (); my %dico_description = (); # cet hash nous permet de juste traiter une fois chaque texte my %dico_files = (); # creer l`objet date pour ecrire les dates dans le log my $date_time = ctime(); #------------------------------------------------------------------------------ # creation des dossiers de sortie my $res = "./Sorties/"; if (! -e $res) { mkdir($res) or die ("Problème avec la création du répertoire de $rep : $!"); } $res = "./Sorties/Sorties_PurePerl/"; if (! -e $res) { mkdir($res) or die ("Problème avec la création du répertoire de $rep : $!\n"); } #------------------------------------------------------------------------------ # sorties etiquetées my $resBAO2 = "./Sorties/Sorties_Tagged/"; if (! -e $resBAO2) { mkdir($resBAO2) or die ("Problème avec la création du répertoire de $rep : $!\n"); } #------------------------------------------------------------------------------ # sortie globale txt open(FILEGLOBALTXT,">:encoding(UTF-8)", $res."SortieGlobale1.txt"); #------------------------------------------------------------------------------ &parcoursarborescencefichiers($rep); #recurse! #------------------------------------------------------------------------------ close FILEGLOBALTXT; #------------------------------------------------------------------------------ # création de la sortie globale xml open(FILEGLOBALXML, ">:encoding(UTF-8)", $res."SortieGlobale1.xml"); print FILEGLOBALXML "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"; print FILEGLOBALXML "<PARCOURS>\n"; print FILEGLOBALXML "<NOM>Bienvenue, Poadey, Cavalcante</NOM>\n"; print FILEGLOBALXML "<FILTRAGE>"; #------------------------------------------------------------------------------ # écrire contenu de la sortie globale xml opendir(DIR, $res) or die "Erreur d'ouverture du repertoire: $!\n"; my @sorties = readdir(DIR); closedir(DIR); foreach my $sortie (@sorties) { if ($sortie=~/(.+?)\.xml$/ && $1 != "SortieGlobale1") { my $rub=$1; open(FILE,">>:encoding(UTF-8)", $res.$sortie); print FILE "</".$rub.">\n";; print FILE "</PARCOURS>\n"; close(FILE); print FILEGLOBALXML "<$rub>\n"; print FILEGLOBALXML ${"DumpXML".$rub}; print FILEGLOBALXML "</$rub>"; } } print FILEGLOBALXML "</FILTRAGE>\n"; print FILEGLOBALXML "</PARCOURS>\n"; close(FILEGLOBALXML); #------------------------------------------------------------------------------ open(FILEGLOBALXML, ">:encoding(UTF-8)", $resBAO2."SortieGlobale2.xml"); print FILEGLOBALXML "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"; print FILEGLOBALXML "<PARCOURS>\n"; print FILEGLOBALXML "<NOM>Bienvenue, Poadey, Cavalcante</NOM>\n"; print FILEGLOBALXML "<FILTRAGE>"; #------------------------------------------------------------------------------ opendir(DIR, $resBAO2) or die "Erreur d'ouverture de repertoire: $!\n"; @sorties = readdir(DIR); closedir(DIR); foreach my $sortie (@sorties) { # se fait sur chaque sortie xml dans chaque rubrique if ($sortie=~/(.+?)\.xml$/ && $1 != "SortieGlobale2") { my $rub = $1; open(FILE,">>:encoding(UTF-8)", $resBAO2.$sortie); print FILE "</".$rub.">\n";; print FILE "</PARCOURS>\n"; close FILE; print FILEGLOBALXML "<$rub>\n"; print FILEGLOBALXML ${"DumpXML2_Tagged".$rub}; print FILEGLOBALXML "</$rub>"; } } #------------------------------------------------------------------------------ print FILEGLOBALXML "</FILTRAGE>\n"; print FILEGLOBALXML "</PARCOURS>\n"; close(FILEGLOBALXML); #------------------------------------------------------------------------------ # imprime le nombre des infos à la fin du programme print "\n" . "files IN = $nb_filesIN\n"; print "items IN = $nb_itemsIN\n"; print "items OUT = $nb_itemsOUT\n"; print "fin.\n"; exit; # fin du main programme #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ # commencement des subroutines #------------------------------------------------------------------------------ # subroutine pour parcourir l'aborescence sub parcoursarborescencefichiers { my $path = shift(@_); # chemin vers le dossier en entrée opendir(DIR, $path) or die "Probleme d'ouverture du dossier: $!\n"; my @files = readdir(DIR); closedir(DIR); #-------------------------------------------- foreach my $file (@files) { next if $file =~ /^\.\.?$/; #si . ou .. $file = $path."/".$file; #si $file est un dossier if (-d $file) { &parcoursarborescencefichiers($file); #recurse! } # faire le traitement si $file est un fichier if (-f $file) { # traiter les fichiers xml seulement if ($file=~/^[^(fil)]+?\.xml$/) { $nb_filesIN++; print $file,"\n"; #lire le fichier xml open(FILE,$file); my $firstLine = <FILE>; my $encodage = ""; #vérifier encodage du fichier xml if($firstLine =~ /encoding= ?['"]([^\'"]+)['"]/) { $encodage = $1; #extraire l'encodage } close(FILE); # si on trouve l'encodage, le fichier est reouvert avec l'encodage correcte if (!($encodage eq "")) { open(FILE,"<:encoding($encodage)",$file); my $texte = ""; #éliminer les retours à ligne dans le fichier [ \n et \r ] while (my $ligne = <FILE>) { $ligne =~ s/\n//g; $ligne =~ s/\r//g; $texte .= $ligne; } close FILE; $texte =~ s/> *?</></g; # coller les balises #----------------------------------------- # extraire rubrique, date et nom $texte =~ /<channel>.*?<title>(.*?)<\/title>.*?<pubDate>(.+?)<\/pubDate>.*?<\/channel>/; # nettoyer les rubriques my $rubrique = &nettoyerRubriques($1); print "RUBRIQUE : $rubrique\n"; # extraire la date my $date = &nettoyerRubriques($2); # nom du fichier my $name = $file; # uniquement les fichiers XML contenant les mises à jour $name =~ s/.*?(20.*)/$1/; #------------------------------------------ # ouvre des balises et écrire dans des fichiers de sortie my $cheminXML=$res.$rubrique.".xml"; # si on n'a pas encore vu le rubrique on doit le créer if (! -e $cheminXML) { # créer un fichier if (!open (FILEOUT,">:encoding(UTF-8)",$cheminXML)) { die "Probleme a la creation du fichier $cheminXML : $!"; } # ouverture des balises XML du début du fichier print FILEOUT "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"; print FILEOUT "<PARCOURS>\n"; print FILEOUT "<NOM>Bienvenue, Poadey, Cavalcante</NOM>\n"; print FILEOUT "<$rubrique>\n"; print FILEOUT "<file>"; print FILEOUT "<name>$name</name>"; print FILEOUT "<date>$date</date>"; print FILEOUT "<items>"; close(FILEOUT); ${"DumpXML"."$rubrique"}=""; } # si le fichier existe déjà else { if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML)) { die "Problème a l'ouverture du fichier $cheminXML : $!\n"; } print FILEOUT "<file>"; print FILEOUT "<name>$name</name>"; print FILEOUT "<date>$date</date>"; print FILEOUT "<items>"; close(FILEOUT); } #------------------------------------------- my $cheminXML_BAO2=$resBAO2.$rubrique.".xml"; # si on n'a pas encore vu le rubrique if (! -e $cheminXML_BAO2) { # créer un fichier if (!open (FILEOUT,">:encoding(UTF-8)",$cheminXML_BAO2)) { die "Probleme a la creation du fichier $cheminXML_BAO2 : $!\n"; } # ouverture des balises XML du début du fichier print FILEOUT "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"; print FILEOUT "<PARCOURS>\n"; print FILEOUT "<NOM>Bienvenue, Poadey, Cavalcante</NOM>\n"; print FILEOUT "<$rubrique>\n"; print FILEOUT "<file>"; print FILEOUT "<name>$name</name>"; print FILEOUT "<date>$date</date>"; print FILEOUT "<items>"; close(FILEOUT); ${"DumpXML_tagged"."$rubrique"}=""; } # si le fichier existe déjà else { if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML_BAO2)) { die "Problème a l'ouverture du fichier $cheminXML_BAO2 : $!\n"; } print FILEOUT "<file>"; print FILEOUT "<name>$file</name>"; print FILEOUT "<date>$date</date>"; print FILEOUT "<items>"; close(FILEOUT); } #--------------------------------------------- # extractions des titres et descriptions while ($texte =~ /<item>.*?<title>(.*?)<\/title>.*?<description>(.*?)<\/description>/g) { my $titre = $1; my $description = $2; $nb_itemsIN++; #----------------------------------------- # nettoyer le texte $titre = &nettoyerTexte($titre); $description = &nettoyerTexte($description); if (!(($titre eq "") or ($description eq ""))) { #----------------------------------------- # convertir si besoin en utf-8 if (uc($encodage) ne "UTF-8") { utf8($titre); utf8($description); } #---------------------------------------------- # regarde si on a déjà vu le texte if (!((exists $dico_titre{$rubrique . $titre}) && (exists $dico_description{$rubrique . $description}))) { $dico_titre{$rubrique . $titre} = "1"; $dico_description{$rubrique . $description} = "1"; $nb_itemsOUT++; #------------------------------------------ # faire l'etiquetage my $titre_tagged = &treetagger($titre); my $description_tagged = &treetagger($description); open(LOG, ">>", "log_bao2.txt"); if(exists $dico_files{$file}){ $count_file = int($dico_files{$file}); $count_file++; %dico_files = ($file => $count_file); } else { %dico_files = ($file => 1); } #creer l`objet date pour ecrire les dates dans le log my $date_time = ctime(); #ecrire le fichier de log avec le nom du fichier et l`heure de lecture print LOG $file." ".$dico_files{$file}."\t\t read on ".$date_time."\n"; # mettre dans les sorties xml if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML)) { die "Problème a l'ouverture du fichier $cheminXML : $!\n"; } print FILEOUT "<item>\n"; print FILEOUT "<titre>" . $titre . "</titre>\n<description>" . $description . "</description>\n"; print FILEOUT "</item>\n"; close(FILEOUT); #---------------------------------------------- # créer un dump pour chaque rubrique ${"DumpXML" . $rubrique} .= "<item>\n<titre>" . $titre . "</titre>\n<description>" . $description . "</description>\n</item>\n"; #---------------------------------------------- # partie de sorties txt my $cheminTXT = $res . $rubrique . ".txt"; # si on n'a pas encore vu la rubrique if (! -e $cheminTXT) { if (!open (FILEGLOBALTXT,">>:encoding(iso-8859-15)",$cheminTXT)) { die "Problème a l'ouverture du fichier $cheminTXT : $!\n"; } # écrire dans le sortie txt print FILEGLOBALTXT "$titre." . " $description.\n"; close(FILEGLOBALTXT); } # si on a déjà vu la rubrique else { if (!open (FILEGLOBALTXT,">>:encoding(iso-8859-15)",$cheminTXT)) { die "Problème a l'ouverture du fichier $cheminTXT : $!\n"; } # écrire dans le sortie txt print FILEGLOBALTXT "$titre." . " $description."; close(FILEGLOBALTXT); } if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML_BAO2)) { die "Problème a l'ouverture du fichier $cheminXML_BAO2 : $!\n"; } print FILEOUT "<item>\n"; print FILEOUT "<titre>".$titre_tagged."</titre>\n<description>".$description_tagged."</description>\n"; print FILEOUT "</item>\n"; close(FILEOUT); # créer un dump pour chaque rubrique ${"DumpXML2_Tagged".$rubrique}.="<item>\n<titre>".$titre_tagged."</titre>\n<description>".$description_tagged."</description>\n</item>\n"; } } } # fermer la balise file pour chaque fichier xml if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML)) { die "Problème a l'ouverture du fichier .$cheminXML : $!\n"; } print FILEOUT "</items>"; print FILEOUT "</file>"; close(FILEOUT); # fermer la balise les fichier xml etiqutée if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML_BAO2)) { die "Problème a l'ouverture du fichier .$cheminXML_BAO2 : $!\n"; } print FILEOUT "</items>"; print FILEOUT "</file>"; close(FILEOUT); } } } } } #------------------------------------------------------------------------------ # subroutine pour nettoyer le texte #------------------------------------------------------------------------------ sub nettoyerTexte { my $tx = $_[0]; $tx =~ s/&/&/g; $tx =~ s/&/&/g; $tx =~ s/"/"/g; $tx =~ s/"/"/g; $tx =~ s/'/'/g; $tx =~ s/'/'/g; $tx =~ s/</</g; $tx =~ s/</</g; $tx =~ s/>/>/g; $tx =~ s/>/>/g; $tx =~ s/ //g; $tx =~ s/ //g; $tx =~ s/£/£/g; $tx =~ s/£/£/g; $tx =~ s/©/©/g; $tx =~ s/«/«/g; $tx =~ s/«/«/g; $tx =~ s/»/»/g; $tx =~ s/»//g; $tx =~ s/É/É/g; $tx =~ s/É/É/g; $tx =~ s/í/î/g; $tx =~ s/î/î/g; $tx =~ s/ï/ï/g; $tx =~ s/ï/ï/g; $tx =~ s/à/à/g; $tx =~ s/à/à/g; $tx =~ s/â/â/g; $tx =~ s/â/â/g; $tx =~ s/ç/ç/g; $tx =~ s/ç/ç/g; $tx =~ s/è/è/g; $tx =~ s/è/è/g; $tx =~ s/é/é/g; $tx =~ s/é/é/g; $tx =~ s/ê/ê/g; $tx =~ s/ê/ê/g; $tx =~ s/ô/ô/g; $tx =~ s/ô/ô/g; $tx =~ s/û/û/g; $tx =~ s/û/û/g; $tx =~ s/ü/ü/g; $tx =~ s/ü/ü/g; $tx =~ s/\x9c/œ/g; $tx =~ s/<br\/\>//g; $tx =~ s/<img.*?\/>//g; $tx =~ s/<.+?>//sg; $tx =~ s/<a.*?>.*?<\/a>//g; $tx =~ s/<![CDATA[(.*?)]]>/$1/g; $tx =~ s/<[^>]>//g; $tx =~ s/\.$//; $tx =~ s/&/et/g; return $tx; } #------------------------------------------------------------------------------ # subroutine pour nettoyer des rubriques #------------------------------------------------------------------------------ sub nettoyerRubriques { my $rubrique = shift; $rubrique =~ s/Le Monde.fr//g; $rubrique =~ s/LeMonde.fr//g; $rubrique =~ s/: Toute l'actualité sur//g; $rubrique =~ s/É/e/g; $rubrique =~ s/é/e/g; $rubrique =~ s/è/e/g; $rubrique =~ s/ê/a/g; $rubrique =~ s/ë/e/g; $rubrique =~ s/ï/i/g; $rubrique =~ s/î/i/g; $rubrique =~ s/à/a/g; $rubrique =~ s/ô/o/g; $rubrique =~ s/,/_/g; $rubrique = uc($rubrique); $rubrique =~ s/ //g; $rubrique =~ s/[\.\:;\'\"\-]+//g; return $rubrique; } #------------------------------------------------------------------------------ # subroutine pour le tokenisation et etiquetage #------------------------------------------------------------------------------ sub treetagger { my $texte = shift; my $temptag; # créer un fichier temporaire pour tagger des morceaux de texte open($temptag, ">:encoding(UTF-8)", "./temptag.txt"); print $temptag $texte; close($temptag); system("perl tokenise-utf8.pl ./temptag.txt | /home/alexandre/tree-tagger/bin/tree-tagger -lemma -token -no-unknown -sgml /home/alexandre/tree-tagger/models/french.par > treetagger.txt"); system("perl ./treetagger2xml-utf8.pl treetagger.txt utf-8"); open(TaggedOUT,"<:encoding(utf-8)","treetagger.txt.xml"); my $tagged_text = ""; #lire la ligne d'en tête du fichier xml étiqueté, pour éviter que cette # ligne soit inclue dans le nouveau fichier xml my $line_den_tete = <TaggedOUT>; while (my $l = <TaggedOUT>) { $tagged_text .= $l; } close(TaggedOUT); return $tagged_text; } # fin des subroutines #------------------------------------------------------------------------------ #------------------------------------------------------------------------------
Módulos Perl
Nós criamos scripts Perl para as Ferramentas, utilizando as funções para excluir as entidades dos arquivos, mas também utilizando os módulos XML::Entities e HTML::Entities. Nós temos então dois scripts diferentes para a Ferramenta 2, ou seja, com e sem módulos do Perl.
Para a Ferramenta 2, nós implementamos o mesmo sistema que para CdF 1, nós limpamos o arquivo XML após a decodificação das entidades.
A inclusão dos módulos:
A utilização dos módulos:
- #!/usr/bin/perl -w
- <<DOC;
- Votre Nom : Bienvenue, Poadey, Cavalcante
- MARS 2015
- usage : perl parcours-arborescence-fichiers repertoire-a-parcourir
- Le programme prend en entrée le nom du répertoire contenant les fichiers
- à traiter
- Le programme construit en sortie un fichier structuré contenant sur chaque
- ligne le nom du fichier et le résultat du filtrage :
- <FICHIER><NOM>du fichier</NOM></FICHIER><CONTENU>du filtrage</CONTENU></FICHIER>
- DOC
- use Unicode::String qw(utf8);
- use utf8;
- use Time::localtime;
- use XML::Entities;
- use HTML::Entities;
- #------------------------------------------------------------------------------
- # des compteurs pour le nombre des items
- my $nb_filesIN = 0;
- my $nb_itemsIN = 0;
- my $nb_itemsOUT = 0;
- #------------------------------------------------------------------------------
- # le répertoire d'entrée contenant les fichiers xml
- my $rep = "$ARGV[0]";
- # regex enlever le slash à la fin du nom du répertoire
- $rep =~ s/[\/]$//;
- #------------------------------------------------------------------------------
- # des hash tables pour vérifier qu'on n'a pas deux fois les même infos
- my %dicoTitre = ();
- my %dicoDescription = ();
- # cet hash controle le nombre de fois que le fichier a ete lu pour ecrire le fichier de log
- my %dico_files = ();
- #creer l`objet date pour ecire la date et l'heure de lecture des fichiers xml dans le fichier de log
- my $date_time = ctime();
- #------------------------------------------------------------------------------
- # creation des dossiers de sortie
- my $res = "../Sorties/";
- if (! -e $res) {
- mkdir($res) or die ("Problème avec la création du répertoire de $rep : $!");
- }
- $res = "../Sorties/1_Sorties_PurePerl/";
- if (! -e $res) {
- mkdir($res) or die ("Problème avec la création du répertoire de $rep : $!\n");
- }
- #------------------------------------------------------------------------------
- # sorties etiquetées
- my $resBAO2 = "../Sorties/2_Sorties_Etiquetees/";
- if (! -e $resBAO2) {
- mkdir($resBAO2) or die ("Problème avec la création du répertoire de $rep : $!\n");
- }
- #------------------------------------------------------------------------------
- # sortie globale txt
- open(FILEGLOBALTXT,">:encoding(UTF-8)", $res."1_SortieGlobale.txt");
- #------------------------------------------------------------------------------
- &parcoursarborescencefichiers($rep); #recurse!
- #------------------------------------------------------------------------------
- close FILEGLOBALTXT;
- #------------------------------------------------------------------------------
- # création de la sortie globale xml
- open(FILEGLOBALXML, ">:encoding(UTF-8)", $res."1_SortieGlobale.xml");
- print FILEGLOBALXML "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
- print FILEGLOBALXML "<PARCOURS>\n";
- print FILEGLOBALXML "<NOM>Bienvenue, Poadey, Cavalcante</NOM>\n";
- print FILEGLOBALXML "<FILTRAGE>";
- #------------------------------------------------------------------------------
- # écrire contenu de la sortie globale xml
- opendir(DIR, $res) or die "Erreur d'ouverture du repertoire: $!\n";
- my @sorties = readdir(DIR);
- closedir(DIR);
- foreach my $sortie (@sorties) {
- if ($sortie=~/(.+?)\.xml$/ && $1 != "1_SortieGlobale") {
- my $rub=$1;
- open(FILE,">>:encoding(UTF-8)", $res.$sortie);
- print FILE "</".$rub.">\n";;
- print FILE "</PARCOURS>\n";
- close(FILE);
- print FILEGLOBALXML "<$rub>\n";
- print FILEGLOBALXML ${"DumpXML".$rub};
- print FILEGLOBALXML "</$rub>";
- }
- }
- print FILEGLOBALXML "</FILTRAGE>\n";
- print FILEGLOBALXML "</PARCOURS>\n";
- close(FILEGLOBALXML);
- #------------------------------------------------------------------------------
- open(FILEGLOBALXML, ">:encoding(UTF-8)", $resBAO2."2_SortieGlobale.xml");
- print FILEGLOBALXML "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
- print FILEGLOBALXML "<PARCOURS>\n";
- print FILEGLOBALXML "<NOM>Bienvenue, Poadey, Cavalcante</NOM>\n";
- print FILEGLOBALXML "<FILTRAGE>";
- #------------------------------------------------------------------------------
- opendir(DIR, $resBAO2) or die "Erreur d'ouverture de repertoire: $!\n";
- @sorties = readdir(DIR);
- closedir(DIR);
- foreach my $sortie (@sorties) {
- # se fait sur chaque sortie xml dans chaque rubrique
- if ($sortie=~/(.+?)\.xml$/ && $1 != "2_SortieGlobale") {
- my $rub = $1;
- open(FILE,">>:encoding(UTF-8)", $resBAO2.$sortie);
- print FILE "</".$rub.">\n";;
- print FILE "</PARCOURS>\n";
- close FILE;
- print FILEGLOBALXML "<$rub>\n";
- print FILEGLOBALXML ${"DumpXML2_Tagged".$rub};
- print FILEGLOBALXML "</$rub>";
- }
- }
- #------------------------------------------------------------------------------
- print FILEGLOBALXML "</FILTRAGE>\n";
- print FILEGLOBALXML "</PARCOURS>\n";
- close(FILEGLOBALXML);
- #------------------------------------------------------------------------------
- # imprime le nombre des infos à la fin du programme
- print "\n" . "nbr files IN = $nb_filesIN\n";
- print "nbr items IN = $nb_itemsIN\n";
- print "nbr items OUT = $nb_itemsOUT\n";
- print "fin du programme.\n";
- exit;
- # fin du main programme
- #------------------------------------------------------------------------------
- #------------------------------------------------------------------------------
- # commencement des subroutines
- #------------------------------------------------------------------------------
- # subroutine pour parcourir l'aborescence
- sub parcoursarborescencefichiers {
- my $path = shift(@_); # chemin vers le dossier en entrée
- opendir(DIR, $path) or die "Probleme d'ouverture du dossier: $!\n";
- my @files = readdir(DIR);
- closedir(DIR);
- #------------------------------------------------------------------------------
- foreach my $file (@files) {
- next if $file =~ /^\.\.?$/; #si . ou ..
- $file = $path."/".$file;
- #si $file est un dossier
- if (-d $file) {
- &parcoursarborescencefichiers($file); #recurse!
- }
- # faire le traitement si $file est un fichier
- if (-f $file) {
- # traiter les fichiers xml seulement
- if ($file=~/^[^(fil)]+?\.xml$/) {
- $nb_filesIN++;
- print $file,"\n";
- #lire le fichier xml
- open(FILE,$file);
- my $firstLine = <FILE>;
- my $encodage = "";
- #vérifier encodage du fichier xml
- if($firstLine =~ /encoding= ?['"]([^\'"]+)['"]/) {
- $encodage = $1; #extraire l'encodage
- }
- close(FILE);
- # si on trouve l'encodage, le fichier est reouvert avec l'encodage correcte
- if (!($encodage eq "")) {
- open(FILE,"<:encoding($encodage)",$file);
- my $texte = "";
- #éliminer les retours à ligne dans le fichier [ \n et \r ]
- while (my $ligne = <FILE>) {
- $ligne =~ s/\n//g;
- $ligne =~ s/\r//g;
- $texte .= $ligne;
- }
- close FILE;
- $texte =~ s/> *?</></g; # coller les balises
- #------------------------------------------------------------------------------
- # extraire rubrique, date et nom
- $texte =~ /<channel>.*?<title>(.*?)<\/title>.*?<pubDate>(.+?)<\/pubDate>.*?<\/channel>/;
- # nettoyer les rubriques
- my $rubrique = &nettoyerRubriques($1);
- print "RUBRIQUE : $rubrique\n";
- # extraire la date
- my $date = &nettoyerRubriques($2);
- # nom du fichier
- my $name = $file;
- # uniquement les fichiers XML contenant les mises à jour
- $name =~ s/.*?(20.*)/$1/;
- #------------------------------------------------------------------------------
- # ouvre des balises et écrire dans des fichiers de sortie
- my $cheminXML=$res.$rubrique.".xml";
- # si on n'a pas encore vu le rubrique on doit le créer
- if (! -e $cheminXML) {
- # créer un fichier
- if (!open (FILEOUT,">:encoding(UTF-8)",$cheminXML)) {
- die "Probleme a la creation du fichier $cheminXML : $!";
- }
- # ouverture des balises XML du début du fichier
- print FILEOUT "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
- print FILEOUT "<PARCOURS>\n";
- print FILEOUT "<NOM>Bienvenue, Poadey, Cavalcante</NOM>\n";
- print FILEOUT "<$rubrique>\n";
- print FILEOUT "<file>";
- print FILEOUT "<name>$name</name>";
- print FILEOUT "<date>$date</date>";
- print FILEOUT "<items>";
- close(FILEOUT);
- ${"DumpXML"."$rubrique"}="";
- }
- # si le fichier existe déjà
- else {
- if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML)) {
- die "Problème a l'ouverture du fichier $cheminXML : $!\n";
- }
- print FILEOUT "<file>";
- print FILEOUT "<name>$name</name>";
- print FILEOUT "<date>$date</date>";
- print FILEOUT "<items>";
- close(FILEOUT);
- }
- #------------------------------------------------------------------------------
- my $cheminXML_BAO2=$resBAO2.$rubrique.".xml";
- # si on n'a pas encore vu le rubrique
- if (! -e $cheminXML_BAO2) {
- # créer un fichier
- if (!open (FILEOUT,">:encoding(UTF-8)",$cheminXML_BAO2)) {
- die "Probleme a la creation du fichier $cheminXML_BAO2 : $!\n";
- }
- # ouverture des balises XML du début du fichier
- print FILEOUT "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
- print FILEOUT "<PARCOURS>\n";
- print FILEOUT "<NOM>Bienvenue, Poadey, Cavalcante</NOM>\n";
- print FILEOUT "<$rubrique>\n";
- print FILEOUT "<file>";
- print FILEOUT "<name>$name</name>";
- print FILEOUT "<date>$date</date>";
- print FILEOUT "<items>";
- close(FILEOUT);
- ${"DumpXML_tagged"."$rubrique"}="";
- }
- # si le fichier existe déjà
- else {
- if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML_BAO2)) {
- die "Problème a l'ouverture du fichier $cheminXML_BAO2 : $!\n";
- }
- print FILEOUT "<file>";
- print FILEOUT "<name>$file</name>";
- print FILEOUT "<date>$date</date>";
- print FILEOUT "<items>";
- close(FILEOUT);
- }
- #------------------------------------------------------------------------------
- # extractions des titres et descriptions
- while ($texte =~ /<item>.*?<title>(.*?)<\/title>.*?<description>(.*?)<\/description>/g)
- {
- my $titre = $1;
- my $description = $2;
- $nb_itemsIN++;
- #------------------------------------------------------------------------------
- # nettoyer le texte
- if (!(exists ($dicoTitre{$titre})) and !(exists ($dicoDescription{$description})))
- {
- $dicoTitre{$titre}++;
- $dicoDescription{$description}++;
- $titre = XML::Entities::decode('all', $titre);
- $descritpion = XML::Entities::decode('all', $description);
- $titre = HTML::Entities::decode($titre);
- $description = HTML::Entities::decode($description);
- $tmptexteBRUT.="$titre \n";
- $tmptexteBRUT.="$description \n";
- $tmptexteXML.="<item><title>$titre</title><description>$description</description></item>\n";
- #--------------------------------------------------------------------------------------
- # nettoyage des balises <description> pour supprimer les balises superflues
- $tmptexteXML =~ s/<img.*?\/><\/description>/<\/description>/g;
- $tmptexteBRUT =~ s/<img.*?\/> \n/\n/g;
- }
- if (!(($titre eq "") or ($description eq ""))) {
- #------------------------------------------------------------------------------
- # convertir si besoin en utf-8
- if (uc($encodage) ne "UTF-8") {
- utf8($titre);
- utf8($description);
- }
- #------------------------------------------------------------------------------
- # regarde si on a déjà vu le texte
- if (!((exists $dicoTitre{$rubrique . $titre}) && (exists $dicoDescription{$rubrique . $description})))
- {
- $dicoTitre{$rubrique . $titre} = "1";
- $dicoDescription{$rubrique . $description} = "1";
- $nb_itemsOUT++;
- #------------------------------------------------------------------------------
- # faire l'etiquetage
- my $titre_tagged = &treetagger($titre);
- my $description_tagged = &treetagger($description);
- open(LOG, ">>", "log_bao2.txt");
- if(exists $dico_files{$file}){
- $count_file = int($dico_files{$file});
- $count_file++;
- %dico_files = ($file => $count_file);
- } else {
- %dico_files = ($file => 1);
- }
- #creer l`objet date pour ecire les date dans le fichier de log
- my $date_time = ctime();
- #ecrire le fichier de log avec le nom du fichier et l`heure de lecture
- print LOG $file." ".$dico_files{$file}."\t\t read on ".$date_time."\n";
- # mettre dans les sorties xml
- if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML)) {
- die "Problème a l'ouverture du fichier $cheminXML : $!\n";
- }
- print FILEOUT "<item>\n";
- print FILEOUT $tmptexteXML;
- print FILEOUT "</item>\n";
- close(FILEOUT);
- #------------------------------------------------------------------------------
- # créer un dump pour chaque rubrique
- ${"DumpXML" . $rubrique} .= $tmptexteXML."\n";
- #------------------------------------------------------------------------------
- # partie de sorties txt
- my $cheminTXT = $res . $rubrique . ".txt";
- # si on n'a pas encore vu la rubrique
- if (! -e $cheminTXT) {
- if (!open (FILEGLOBALTXT,">:encoding(iso-8859-15)",$cheminTXT)) {
- die "Problème a l'ouverture du fichier $cheminTXT : $!\n";
- }
- # écrire dans le sortie txt
- print FILEGLOBALTXT $tmptexteBRUT;
- close(FILEGLOBALTXT);
- }
- # si on a déjà vu la rubrique
- else {
- if (!open (FILEGLOBALTXT,">>:encoding(iso-8859-15)",$cheminTXT)) {
- die "Problème a l'ouverture du fichier $cheminTXT : $!\n";
- }
- # écrire dans la sortie txt
- print FILEGLOBALTXT $tmptexteBRUT;
- close(FILEGLOBALTXT);
- }
- if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML_BAO2)) {
- die "Problème a l'ouverture du fichier $cheminXML_BAO2 : $!\n";
- }
- print FILEOUT "<item>\n";
- print FILEOUT $tmptexteXML;
- print FILEOUT "</item>\n";
- close(FILEOUT);
- # créer un dump pour chaque rubrique
- ${"DumpXML2_Tagged".$rubrique}.= $tmptexteXML."\n";
- }
- }
- }
- # fermer la balise file pour chaque fichier xml
- if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML))
- {
- die "Problème a l'ouverture du fichier .$cheminXML : $!\n";
- }
- print FILEOUT "</items>";
- print FILEOUT "</file>";
- close(FILEOUT);
- # fermer la balise les fichier xml etiqutée
- if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML_BAO2)) {
- die "Problème a l'ouverture du fichier .$cheminXML_BAO2 : $!\n";
- }
- print FILEOUT "</items>";
- print FILEOUT "</file>";
- close(FILEOUT);
- }
- }
- }
- }
- }
- #------------------------------------------------------------------------------
- # subroutine pour nettoyer des rubriques
- #------------------------------------------------------------------------------
- sub nettoyerRubriques {
- my $rubrique = shift;
- $rubrique =~ s/Le Monde.fr//g;
- $rubrique =~ s/LeMonde.fr//g;
- $rubrique =~ s/: Toute l'actualité sur//g;
- $rubrique =~ s/É/e/g;
- $rubrique =~ s/é/e/g;
- $rubrique =~ s/è/e/g;
- $rubrique =~ s/ê/a/g;
- $rubrique =~ s/ë/e/g;
- $rubrique =~ s/ï/i/g;
- $rubrique =~ s/î/i/g;
- $rubrique =~ s/à/a/g;
- $rubrique =~ s/ô/o/g;
- $rubrique =~ s/,/_/g;
- $rubrique = uc($rubrique);
- $rubrique =~ s/ //g;
- $rubrique =~ s/[\.\:;\'\"\-]+//g;
- return $rubrique;
- }
- #------------------------------------------------------------------------------
- # subroutine pour tokenisation et etiquetage
- #------------------------------------------------------------------------------
- sub treetagger {
- my $texte = shift;
- my $temptag;
- # créer un fichier temporaire pour tagger des morceaux de texte
- open($temptag, ">:encoding(UTF-8)", "./temptag.txt");
- print $temptag $texte;
- close($temptag);
- system("perl tokenise-utf8.pl ./temptag.txt | tree-tagger.exe -lemma -token -no-unknown -sgml ./french.par > treetagger.txt");
- system("perl treetagger2xml-utf8.pl treetagger.txt utf-8");
- open(TaggedOUT,"<:encoding(utf-8)","treetagger.txt.xml");
- my $tagged_text = "";
- #lire la ligne d'en tête du fichier xml étiqueté, pour éviter que cette ligne soit incluse dans le nouveau fichier xml
- my $line_den_tete = <TaggedOUT>;
- while (my $l = <TaggedOUT>) {
- $tagged_text .= $l;
- }
- close(TaggedOUT);
- return $tagged_text;
- }
- # fin des subroutines
- #------------------------------------------------------------------------------
- #------------------------------------------------------------------------------
#!/usr/bin/perl -w <<DOC; Votre Nom : Bienvenue, Poadey, Cavalcante MARS 2015 usage : perl parcours-arborescence-fichiers repertoire-a-parcourir Le programme prend en entrée le nom du répertoire contenant les fichiers à traiter Le programme construit en sortie un fichier structuré contenant sur chaque ligne le nom du fichier et le résultat du filtrage : <FICHIER><NOM>du fichier</NOM></FICHIER><CONTENU>du filtrage</CONTENU></FICHIER> DOC use Unicode::String qw(utf8); use utf8; use Time::localtime; use XML::Entities; use HTML::Entities; #------------------------------------------------------------------------------ # des compteurs pour le nombre des items my $nb_filesIN = 0; my $nb_itemsIN = 0; my $nb_itemsOUT = 0; #------------------------------------------------------------------------------ # le répertoire d'entrée contenant les fichiers xml my $rep = "$ARGV[0]"; # regex enlever le slash à la fin du nom du répertoire $rep =~ s/[\/]$//; #------------------------------------------------------------------------------ # des hash tables pour vérifier qu'on n'a pas deux fois les même infos my %dicoTitre = (); my %dicoDescription = (); # cet hash controle le nombre de fois que le fichier a ete lu pour ecrire le fichier de log my %dico_files = (); #creer l`objet date pour ecire la date et l'heure de lecture des fichiers xml dans le fichier de log my $date_time = ctime(); #------------------------------------------------------------------------------ # creation des dossiers de sortie my $res = "../Sorties/"; if (! -e $res) { mkdir($res) or die ("Problème avec la création du répertoire de $rep : $!"); } $res = "../Sorties/1_Sorties_PurePerl/"; if (! -e $res) { mkdir($res) or die ("Problème avec la création du répertoire de $rep : $!\n"); } #------------------------------------------------------------------------------ # sorties etiquetées my $resBAO2 = "../Sorties/2_Sorties_Etiquetees/"; if (! -e $resBAO2) { mkdir($resBAO2) or die ("Problème avec la création du répertoire de $rep : $!\n"); } #------------------------------------------------------------------------------ # sortie globale txt open(FILEGLOBALTXT,">:encoding(UTF-8)", $res."1_SortieGlobale.txt"); #------------------------------------------------------------------------------ &parcoursarborescencefichiers($rep); #recurse! #------------------------------------------------------------------------------ close FILEGLOBALTXT; #------------------------------------------------------------------------------ # création de la sortie globale xml open(FILEGLOBALXML, ">:encoding(UTF-8)", $res."1_SortieGlobale.xml"); print FILEGLOBALXML "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"; print FILEGLOBALXML "<PARCOURS>\n"; print FILEGLOBALXML "<NOM>Bienvenue, Poadey, Cavalcante</NOM>\n"; print FILEGLOBALXML "<FILTRAGE>"; #------------------------------------------------------------------------------ # écrire contenu de la sortie globale xml opendir(DIR, $res) or die "Erreur d'ouverture du repertoire: $!\n"; my @sorties = readdir(DIR); closedir(DIR); foreach my $sortie (@sorties) { if ($sortie=~/(.+?)\.xml$/ && $1 != "1_SortieGlobale") { my $rub=$1; open(FILE,">>:encoding(UTF-8)", $res.$sortie); print FILE "</".$rub.">\n";; print FILE "</PARCOURS>\n"; close(FILE); print FILEGLOBALXML "<$rub>\n"; print FILEGLOBALXML ${"DumpXML".$rub}; print FILEGLOBALXML "</$rub>"; } } print FILEGLOBALXML "</FILTRAGE>\n"; print FILEGLOBALXML "</PARCOURS>\n"; close(FILEGLOBALXML); #------------------------------------------------------------------------------ open(FILEGLOBALXML, ">:encoding(UTF-8)", $resBAO2."2_SortieGlobale.xml"); print FILEGLOBALXML "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"; print FILEGLOBALXML "<PARCOURS>\n"; print FILEGLOBALXML "<NOM>Bienvenue, Poadey, Cavalcante</NOM>\n"; print FILEGLOBALXML "<FILTRAGE>"; #------------------------------------------------------------------------------ opendir(DIR, $resBAO2) or die "Erreur d'ouverture de repertoire: $!\n"; @sorties = readdir(DIR); closedir(DIR); foreach my $sortie (@sorties) { # se fait sur chaque sortie xml dans chaque rubrique if ($sortie=~/(.+?)\.xml$/ && $1 != "2_SortieGlobale") { my $rub = $1; open(FILE,">>:encoding(UTF-8)", $resBAO2.$sortie); print FILE "</".$rub.">\n";; print FILE "</PARCOURS>\n"; close FILE; print FILEGLOBALXML "<$rub>\n"; print FILEGLOBALXML ${"DumpXML2_Tagged".$rub}; print FILEGLOBALXML "</$rub>"; } } #------------------------------------------------------------------------------ print FILEGLOBALXML "</FILTRAGE>\n"; print FILEGLOBALXML "</PARCOURS>\n"; close(FILEGLOBALXML); #------------------------------------------------------------------------------ # imprime le nombre des infos à la fin du programme print "\n" . "nbr files IN = $nb_filesIN\n"; print "nbr items IN = $nb_itemsIN\n"; print "nbr items OUT = $nb_itemsOUT\n"; print "fin du programme.\n"; exit; # fin du main programme #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ # commencement des subroutines #------------------------------------------------------------------------------ # subroutine pour parcourir l'aborescence sub parcoursarborescencefichiers { my $path = shift(@_); # chemin vers le dossier en entrée opendir(DIR, $path) or die "Probleme d'ouverture du dossier: $!\n"; my @files = readdir(DIR); closedir(DIR); #------------------------------------------------------------------------------ foreach my $file (@files) { next if $file =~ /^\.\.?$/; #si . ou .. $file = $path."/".$file; #si $file est un dossier if (-d $file) { &parcoursarborescencefichiers($file); #recurse! } # faire le traitement si $file est un fichier if (-f $file) { # traiter les fichiers xml seulement if ($file=~/^[^(fil)]+?\.xml$/) { $nb_filesIN++; print $file,"\n"; #lire le fichier xml open(FILE,$file); my $firstLine = <FILE>; my $encodage = ""; #vérifier encodage du fichier xml if($firstLine =~ /encoding= ?['"]([^\'"]+)['"]/) { $encodage = $1; #extraire l'encodage } close(FILE); # si on trouve l'encodage, le fichier est reouvert avec l'encodage correcte if (!($encodage eq "")) { open(FILE,"<:encoding($encodage)",$file); my $texte = ""; #éliminer les retours à ligne dans le fichier [ \n et \r ] while (my $ligne = <FILE>) { $ligne =~ s/\n//g; $ligne =~ s/\r//g; $texte .= $ligne; } close FILE; $texte =~ s/> *?</></g; # coller les balises #------------------------------------------------------------------------------ # extraire rubrique, date et nom $texte =~ /<channel>.*?<title>(.*?)<\/title>.*?<pubDate>(.+?)<\/pubDate>.*?<\/channel>/; # nettoyer les rubriques my $rubrique = &nettoyerRubriques($1); print "RUBRIQUE : $rubrique\n"; # extraire la date my $date = &nettoyerRubriques($2); # nom du fichier my $name = $file; # uniquement les fichiers XML contenant les mises à jour $name =~ s/.*?(20.*)/$1/; #------------------------------------------------------------------------------ # ouvre des balises et écrire dans des fichiers de sortie my $cheminXML=$res.$rubrique.".xml"; # si on n'a pas encore vu le rubrique on doit le créer if (! -e $cheminXML) { # créer un fichier if (!open (FILEOUT,">:encoding(UTF-8)",$cheminXML)) { die "Probleme a la creation du fichier $cheminXML : $!"; } # ouverture des balises XML du début du fichier print FILEOUT "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"; print FILEOUT "<PARCOURS>\n"; print FILEOUT "<NOM>Bienvenue, Poadey, Cavalcante</NOM>\n"; print FILEOUT "<$rubrique>\n"; print FILEOUT "<file>"; print FILEOUT "<name>$name</name>"; print FILEOUT "<date>$date</date>"; print FILEOUT "<items>"; close(FILEOUT); ${"DumpXML"."$rubrique"}=""; } # si le fichier existe déjà else { if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML)) { die "Problème a l'ouverture du fichier $cheminXML : $!\n"; } print FILEOUT "<file>"; print FILEOUT "<name>$name</name>"; print FILEOUT "<date>$date</date>"; print FILEOUT "<items>"; close(FILEOUT); } #------------------------------------------------------------------------------ my $cheminXML_BAO2=$resBAO2.$rubrique.".xml"; # si on n'a pas encore vu le rubrique if (! -e $cheminXML_BAO2) { # créer un fichier if (!open (FILEOUT,">:encoding(UTF-8)",$cheminXML_BAO2)) { die "Probleme a la creation du fichier $cheminXML_BAO2 : $!\n"; } # ouverture des balises XML du début du fichier print FILEOUT "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"; print FILEOUT "<PARCOURS>\n"; print FILEOUT "<NOM>Bienvenue, Poadey, Cavalcante</NOM>\n"; print FILEOUT "<$rubrique>\n"; print FILEOUT "<file>"; print FILEOUT "<name>$name</name>"; print FILEOUT "<date>$date</date>"; print FILEOUT "<items>"; close(FILEOUT); ${"DumpXML_tagged"."$rubrique"}=""; } # si le fichier existe déjà else { if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML_BAO2)) { die "Problème a l'ouverture du fichier $cheminXML_BAO2 : $!\n"; } print FILEOUT "<file>"; print FILEOUT "<name>$file</name>"; print FILEOUT "<date>$date</date>"; print FILEOUT "<items>"; close(FILEOUT); } #------------------------------------------------------------------------------ # extractions des titres et descriptions while ($texte =~ /<item>.*?<title>(.*?)<\/title>.*?<description>(.*?)<\/description>/g) { my $titre = $1; my $description = $2; $nb_itemsIN++; #------------------------------------------------------------------------------ # nettoyer le texte if (!(exists ($dicoTitre{$titre})) and !(exists ($dicoDescription{$description}))) { $dicoTitre{$titre}++; $dicoDescription{$description}++; $titre = XML::Entities::decode('all', $titre); $descritpion = XML::Entities::decode('all', $description); $titre = HTML::Entities::decode($titre); $description = HTML::Entities::decode($description); $tmptexteBRUT.="$titre \n"; $tmptexteBRUT.="$description \n"; $tmptexteXML.="<item><title>$titre</title><description>$description</description></item>\n"; #-------------------------------------------------------------------------------------- # nettoyage des balises <description> pour supprimer les balises superflues $tmptexteXML =~ s/<img.*?\/><\/description>/<\/description>/g; $tmptexteBRUT =~ s/<img.*?\/> \n/\n/g; } if (!(($titre eq "") or ($description eq ""))) { #------------------------------------------------------------------------------ # convertir si besoin en utf-8 if (uc($encodage) ne "UTF-8") { utf8($titre); utf8($description); } #------------------------------------------------------------------------------ # regarde si on a déjà vu le texte if (!((exists $dicoTitre{$rubrique . $titre}) && (exists $dicoDescription{$rubrique . $description}))) { $dicoTitre{$rubrique . $titre} = "1"; $dicoDescription{$rubrique . $description} = "1"; $nb_itemsOUT++; #------------------------------------------------------------------------------ # faire l'etiquetage my $titre_tagged = &treetagger($titre); my $description_tagged = &treetagger($description); open(LOG, ">>", "log_bao2.txt"); if(exists $dico_files{$file}){ $count_file = int($dico_files{$file}); $count_file++; %dico_files = ($file => $count_file); } else { %dico_files = ($file => 1); } #creer l`objet date pour ecire les date dans le fichier de log my $date_time = ctime(); #ecrire le fichier de log avec le nom du fichier et l`heure de lecture print LOG $file." ".$dico_files{$file}."\t\t read on ".$date_time."\n"; # mettre dans les sorties xml if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML)) { die "Problème a l'ouverture du fichier $cheminXML : $!\n"; } print FILEOUT "<item>\n"; print FILEOUT $tmptexteXML; print FILEOUT "</item>\n"; close(FILEOUT); #------------------------------------------------------------------------------ # créer un dump pour chaque rubrique ${"DumpXML" . $rubrique} .= $tmptexteXML."\n"; #------------------------------------------------------------------------------ # partie de sorties txt my $cheminTXT = $res . $rubrique . ".txt"; # si on n'a pas encore vu la rubrique if (! -e $cheminTXT) { if (!open (FILEGLOBALTXT,">:encoding(iso-8859-15)",$cheminTXT)) { die "Problème a l'ouverture du fichier $cheminTXT : $!\n"; } # écrire dans le sortie txt print FILEGLOBALTXT $tmptexteBRUT; close(FILEGLOBALTXT); } # si on a déjà vu la rubrique else { if (!open (FILEGLOBALTXT,">>:encoding(iso-8859-15)",$cheminTXT)) { die "Problème a l'ouverture du fichier $cheminTXT : $!\n"; } # écrire dans la sortie txt print FILEGLOBALTXT $tmptexteBRUT; close(FILEGLOBALTXT); } if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML_BAO2)) { die "Problème a l'ouverture du fichier $cheminXML_BAO2 : $!\n"; } print FILEOUT "<item>\n"; print FILEOUT $tmptexteXML; print FILEOUT "</item>\n"; close(FILEOUT); # créer un dump pour chaque rubrique ${"DumpXML2_Tagged".$rubrique}.= $tmptexteXML."\n"; } } } # fermer la balise file pour chaque fichier xml if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML)) { die "Problème a l'ouverture du fichier .$cheminXML : $!\n"; } print FILEOUT "</items>"; print FILEOUT "</file>"; close(FILEOUT); # fermer la balise les fichier xml etiqutée if (!open (FILEOUT,">>:encoding(UTF-8)",$cheminXML_BAO2)) { die "Problème a l'ouverture du fichier .$cheminXML_BAO2 : $!\n"; } print FILEOUT "</items>"; print FILEOUT "</file>"; close(FILEOUT); } } } } } #------------------------------------------------------------------------------ # subroutine pour nettoyer des rubriques #------------------------------------------------------------------------------ sub nettoyerRubriques { my $rubrique = shift; $rubrique =~ s/Le Monde.fr//g; $rubrique =~ s/LeMonde.fr//g; $rubrique =~ s/: Toute l'actualité sur//g; $rubrique =~ s/É/e/g; $rubrique =~ s/é/e/g; $rubrique =~ s/è/e/g; $rubrique =~ s/ê/a/g; $rubrique =~ s/ë/e/g; $rubrique =~ s/ï/i/g; $rubrique =~ s/î/i/g; $rubrique =~ s/à/a/g; $rubrique =~ s/ô/o/g; $rubrique =~ s/,/_/g; $rubrique = uc($rubrique); $rubrique =~ s/ //g; $rubrique =~ s/[\.\:;\'\"\-]+//g; return $rubrique; } #------------------------------------------------------------------------------ # subroutine pour tokenisation et etiquetage #------------------------------------------------------------------------------ sub treetagger { my $texte = shift; my $temptag; # créer un fichier temporaire pour tagger des morceaux de texte open($temptag, ">:encoding(UTF-8)", "./temptag.txt"); print $temptag $texte; close($temptag); system("perl tokenise-utf8.pl ./temptag.txt | tree-tagger.exe -lemma -token -no-unknown -sgml ./french.par > treetagger.txt"); system("perl treetagger2xml-utf8.pl treetagger.txt utf-8"); open(TaggedOUT,"<:encoding(utf-8)","treetagger.txt.xml"); my $tagged_text = ""; #lire la ligne d'en tête du fichier xml étiqueté, pour éviter que cette ligne soit incluse dans le nouveau fichier xml my $line_den_tete = <TaggedOUT>; while (my $l = <TaggedOUT>) { $tagged_text .= $l; } close(TaggedOUT); return $tagged_text; } # fin des subroutines #------------------------------------------------------------------------------ #------------------------------------------------------------------------------
Exemplo de resultados da Ferramenta 2
Os resultados da Ferramenta 2 estão em formatos diferentes: .xml, .txt e .cnr (extensão do Cordial).
Um exemplo de saída TreeTagger em formato XML.
Um exemplo de saída TXT (os mesmo que na Ferramenta 1)
Exemplo da saída do Cordial em formato CNR.
O que a Ferramenta 3 faz?
A Ferramenta 3 é composta de dois* scripts diferentes, um para cada saída(TreeTagger e Cordial). Os programas buscam nas saídas padrões morfosintáticos específicos (ex. substantivo-preposição-substantivo).
Recapitulação dos restultados tratados pela Ferramenta 3:
Exemplo de saída do TreeTagger
Exemplo de saída do Cordial
Para este programa, nós realizamos duas abordagens diferenes. Alguns programas necessitam de um arquivos externo TXT que contém os padrões morfosintáticos que estamos procurando e outros são inclusos diretamente nos script. Nas versões finais, nós podemos verificar que nós utilizamos a primeira opção. A utilização de um arquivo externo contendo os padrões facilita a modificição da pesquisa. O mesmo não pode ser dito sobre a mudança de padrões quando eles estão inclusos na estrutura do script.
Esta parte possue também dois arquivos XSL qui não contém código Perl, mas que produzem resultados muito similares àqueles produzidos pelos scripts. XSL é o acrônimo de Extensible Stylesheet Language. Os dois arquivos que nós possuímos são folhas de estilo para os nossos arquivos XMl que nos permetem exiber os elementos contidos nas tags que estamos buscando.
Nosso algoritmo lê cada ítem na terceira coluna do arquivo (a etiqueta de parte do discurso) e verifica se ela coincide com o primeiro ítem do padrão desejado. Caso nao, o script segue para os próximo ítem no arquivo. Caso sim, o script segue a verificação para se certificar que o próximo ítem combina com o próximo ítem na lista de padrões estabelecidade pelo usuário. Se a sequência combina até, ela é extraída e considerada como "compatível". Abaixo nós temos um diagrama básico que deve ser lido da esquerda para direita, de cima para baixo que ilustra o funcionamento do script.
*Claro nós poderíamos escrever um único script que trataria ambos os casos. Porém, é melhor ter dois script para estocar os dados separadamente e limpos.
Os métodos de três professores diferentes para extrair as sequências morfosintáticas a partir dos dados obtidos via Cordial e TreeTagger.
Extração das sequências morfosintáticas a partir de dados Cordial
- #!/usr/bin/perl
- <<DOC;
- prend en entrée un fichier issu de treetagger
- et un fichier de patrons morphosyntaxiques et
- extrait suites de tokens correspondant aux patrons morpho-syntaxiques
- DOC
- open(FIC, $ARGV[0]) or die "impossible ouvrir $ARGV[0] : $!";
- print "choisis nom de fichier pour contenir termes extraits\n";
- my $fic=<STDIN>;
- open(FIC1, ">$fic");
- my $i=0;
- my $j=0;
- my $k=0;
- my @token=();
- while (<FIC>)
- {
- my $ligne=$_;
- chomp $ligne;
- my @liste=split(/\t/,$ligne);
- push(@token, $liste[$i++]." ");
- push(@lemme, "$liste[$i++]" ." ");
- push(@patron, "$liste[$i++]" ." ");
- $i=0;
- }
- #on a 3 listes @token, @lemme, @patron
- @sous_patron=();
- while (defined($element_patron=shift(@patron)))
- {
- $element_patron=~s/\n//;
- if ($element_patron !~ "PCTFORTE")
- {
- push(@sous_patron, $element_patron);
- $j++;
- next;
- }
- my @sous_token=@token[$k..$j-1];
- &cherche_patron(@sous_patron);
- @sous_patron=();
- $k=$j+1;
- #print "tape return pour continuer";
- #my $reponse=<STDIN>;
- $j++;
- }
- #=============================================
- sub cherche_patron
- {
- my @liste=@_;
- my $suite_de_patrons=join("",@liste);
- $z=0;
- $nb=0;
- open(FIC, "$ARGV[1]");
- while(<FIC>)
- {
- $nb=0;
- $ligne=$_;
- chomp $ligne;
- #print "voici le patron traité : $ligne\n";
- while ($ligne=~m/ /g) {$nb++};
- $nb++;
- while ($suite_de_patrons=~m/$ligne/g)
- {
- my $avant=substr ($suite_de_patrons, 0, pos($suite_de_patrons)-length($&));
- while ($avant=~m/ /g) {$z++};
- print FIC1 "@token[$k+$z..$k+$z+$nb-1]\n";
- #print "tape sur return pour continuer\n";
- #my $reponse=<STDIN>;
- $z=0;
- }
- }
- }
#!/usr/bin/perl <<DOC; prend en entrée un fichier issu de treetagger et un fichier de patrons morphosyntaxiques et extrait suites de tokens correspondant aux patrons morpho-syntaxiques DOC open(FIC, $ARGV[0]) or die "impossible ouvrir $ARGV[0] : $!"; print "choisis nom de fichier pour contenir termes extraits\n"; my $fic=<STDIN>; open(FIC1, ">$fic"); my $i=0; my $j=0; my $k=0; my @token=(); while (<FIC>) { my $ligne=$_; chomp $ligne; my @liste=split(/\t/,$ligne); push(@token, $liste[$i++]." "); push(@lemme, "$liste[$i++]" ." "); push(@patron, "$liste[$i++]" ." "); $i=0; } #on a 3 listes @token, @lemme, @patron @sous_patron=(); while (defined($element_patron=shift(@patron))) { $element_patron=~s/\n//; if ($element_patron !~ "PCTFORTE") { push(@sous_patron, $element_patron); $j++; next; } my @sous_token=@token[$k..$j-1]; &cherche_patron(@sous_patron); @sous_patron=(); $k=$j+1; #print "tape return pour continuer"; #my $reponse=<STDIN>; $j++; } #============================================= sub cherche_patron { my @liste=@_; my $suite_de_patrons=join("",@liste); $z=0; $nb=0; open(FIC, "$ARGV[1]"); while(<FIC>) { $nb=0; $ligne=$_; chomp $ligne; #print "voici le patron traité : $ligne\n"; while ($ligne=~m/ /g) {$nb++}; $nb++; while ($suite_de_patrons=~m/$ligne/g) { my $avant=substr ($suite_de_patrons, 0, pos($suite_de_patrons)-length($&)); while ($avant=~m/ /g) {$z++}; print FIC1 "@token[$k+$z..$k+$z+$nb-1]\n"; #print "tape sur return pour continuer\n"; #my $reponse=<STDIN>; $z=0; } } }
Dois scripts que extraem sequências morfosintáticas a partir de dados TreeTagger e Cordial.
O primeiro script extrai todos os "substantivos-adjetivos" dos dados TreeTagger.
- open(FILE,"$ARGV[0]");
- #--------------------------------------------
- # le patron cherché ici est du type NOM ADJ"
- #--------------------------------------------
- my @lignes = <FILE>;
- close(FILE);
- while (@lignes) {
- my $ligne = shift(@lignes);
- chomp $ligne;
- my $sequence = "";
- my $longueur = 0;
- if ( $ligne =~ /<element><data type=\"type\">NOM<\/data><data type=\"lemma\">[^<]+<\/data><data type=\"string\">([^<]+)<\/data><\/element>/) {
- my $forme = $1;
- $sequence .= $forme;
- $longueur = 1;
- my $nextligne = $lignes[0];
- if ( $nextligne =~ /<element><data type=\"type\">ADJ<\/data><data type=\"lemma\">[^<]+<\/data><data type=\"string\">([^<]+)<\/data><\/element>/) {
- my $forme = $1;
- $sequence .= " " . $forme;
- $longueur = 2;
- }
- }
- if ($longueur == 2) {
- print $sequence . "\n";
- }
- }
open(FILE,"$ARGV[0]"); #-------------------------------------------- # le patron cherché ici est du type NOM ADJ" #-------------------------------------------- my @lignes = <FILE>; close(FILE); while (@lignes) { my $ligne = shift(@lignes); chomp $ligne; my $sequence = ""; my $longueur = 0; if ( $ligne =~ /<element><data type=\"type\">NOM<\/data><data type=\"lemma\">[^<]+<\/data><data type=\"string\">([^<]+)<\/data><\/element>/) { my $forme = $1; $sequence .= $forme; $longueur = 1; my $nextligne = $lignes[0]; if ( $nextligne =~ /<element><data type=\"type\">ADJ<\/data><data type=\"lemma\">[^<]+<\/data><data type=\"string\">([^<]+)<\/data><\/element>/) { my $forme = $1; $sequence .= " " . $forme; $longueur = 2; } } if ($longueur == 2) { print $sequence . "\n"; } }
O segundo script extrai todas as sequências "substantivo-preposição" dos dados Cordial.
- open(FILE,"$ARGV[0]");
- #--------------------------------------------
- # le patron cherché ici est du type NOM PREP NOM
- #--------------------------------------------
- my @lignes = <FILE>;
- close(FILE);
- while (@lignes) {
- my $ligne = shift(@lignes);
- chomp $ligne;
- my $sequence = "";
- my $longueur = 0;
- if ( $ligne =~ /^([^\t]+)\t[^\t]+\tNC.*/) {
- my $forme = $1;
- $sequence .= $forme;
- $longueur = 1;
- my $nextligne = $lignes[0];
- if ( $nextligne =~ /^([^\t]+)\t[^\t]+\tPREP.*/) {
- my $forme = $1;
- $sequence .= " " . $forme;
- $longueur = 2;
- my $next_nextligne = $lignes[1];
- if ( $next_nextligne =~ /^([^\t]+)\t[^\t]+\tNC.*/) {
- my $forme = $1;
- $sequence .= " " . $forme;
- $longueur = 3;
- }
- }
- }
- if ($longueur == 3) {
- print $sequence . "\n";
- }
- }
open(FILE,"$ARGV[0]"); #-------------------------------------------- # le patron cherché ici est du type NOM PREP NOM #-------------------------------------------- my @lignes = <FILE>; close(FILE); while (@lignes) { my $ligne = shift(@lignes); chomp $ligne; my $sequence = ""; my $longueur = 0; if ( $ligne =~ /^([^\t]+)\t[^\t]+\tNC.*/) { my $forme = $1; $sequence .= $forme; $longueur = 1; my $nextligne = $lignes[0]; if ( $nextligne =~ /^([^\t]+)\t[^\t]+\tPREP.*/) { my $forme = $1; $sequence .= " " . $forme; $longueur = 2; my $next_nextligne = $lignes[1]; if ( $next_nextligne =~ /^([^\t]+)\t[^\t]+\tNC.*/) { my $forme = $1; $sequence .= " " . $forme; $longueur = 3; } } } if ($longueur == 3) { print $sequence . "\n"; } }
Extração de sequências morfosintáticas a partir de dados TreeTagger.
- #/usr/bin/perl
- <<DOC;
- Nom : Rachid Belmouhoub
- Avril 2012
- usage : perl bao3_rb_new.pl fichier_tag fichier_motif
- DOC
- use strict;
- use utf8;
- use XML::LibXML;
- # Définition globale des encodage d'entrée et sortie du script à utf8
- binmode STDIN, ':encoding(utf8)';
- binmode STDOUT, ':encoding(utf8)';
- # On vérifie le nombre d'arguments de l'appel au script ($0 : le nom du script)
- if($#ARGV!=1){print "usage : perl $0 fichier_tag fichier_motif";exit;}
- # Enregistrement des arguments de la ligne de commande dans les variables idoines
- my $tag_file= shift @ARGV;
- my $patterns_file = shift @ARGV;
- # création de l'objet XML::XPath pour explorer le fichier de sortie tree-tagger XML
- my $xp = XML::LibXML->new(XML_LIBXML_RECOVER => 2);
- $xp->recover_silently(1);
- my $dom = $xp->load_xml( location => $tag_file );
- my $root = $dom->getDocumentElement();
- my $xpc = XML::LibXML::XPathContext->new($root);
- # Ouverture du fichiers de motifs
- open(PATTERNSFILE, $patterns_file) or die "can't open $patterns_file: $!\n";
- # lecture du fichier contenant les motifs, un motif par ligne (par exemple : NOM ADJ)
- while (my $ligne = <PATTERNSFILE>) {
- # Appel à la procédure d'extraction des motifs
- &extract_pattern($ligne);
- }
- # Fermeture du fichiers de motifs
- close(PATTERNSFILE);
- # routine de construction des chemins XPath
- sub construit_XPath{
- # On récupère la ligne du motif recherché
- my $local_ligne=shift @_;
- # initialisation du chemin XPath
- my $search_path="";
- # on supprime avec la fonction chomp un éventuel retour à la ligne
- chomp($local_ligne);
- # on élimine un éveltuel retour chariot hérité de windows
- $local_ligne=~ s/\r$//;
- # Construction au moyen de la fonction split d'un tableau dont chaque élément a pour valeur un élément du motif recherché
- my @tokens=split(/ /,$local_ligne);
- # On commence ici la construction du chemin XPath
- # Ce chemin correspond au premier noeud "element" de l'arbre XML qui répond au motif cherché
- $search_path="//element[contains(data[\@type=\"type\"],\"$tokens[0]\")]";
- # Initialisation du compteur pour la boucle de construction du chemin XPath
- my $i=1;
- while ($i < $#tokens) {
- $search_path.="[following-sibling::element[1][contains(data[\@type=\"type\"],\"$tokens[$i]\")]";
- $i++;
- }
- my $search_path_suffix="]";
- # on utilise l'opérateur x qui permet de répéter la chaine de caractère à sa gauche autant de fois que l'entier à sa droite,
- # soit $i fois $search_path_suffix
- $search_path_suffix=$search_path_suffix x $i;
- # le chemin XPath final
- $search_path.="[following-sibling::element[1][contains(data[\@type=\"type\"],\"".$tokens[$#tokens]."\")]"
- .$search_path_suffix;
- # print "$search_path\n";
- # on renvoie à la procédure appelante le chein XPath et le tableau des éléments du motif
- return ($search_path,@tokens);
- }
- # routine d'extraction du motif
- sub extract_pattern{
- # On récupère la ligne du motif recherché
- my $ext_pat_ligne= shift @_;
- # Appel de la fonction construit_XPath pour le motif lu à la ligne courrante du fichier de motif
- my ($search_path,@tokens) = &construit_XPath($ext_pat_ligne);
- # définition du nom du fichier de résultats pour le motif en utilisant la fonction join
- my $match_file = "res_extract-".join('_', @tokens).".txt";
- # Ouverture du fichiers de résultats encodé en UTF-8
- open(MATCHFILE,">:encoding(UTF-8)", "$match_file") or die "can't open $match_file: $!\n";
- # création de l'objet XML::XPath pour explorer le fichier de sortie tree-tagger XML
- # Parcours des noeuds du ficher XML correspondant au motif, au moyen de la méthode findnodes
- # qui prend pour argument le chemin XPath construit précédement
- # avec la fonction "construit_XPath"
- my @nodes=$root->findnodes($search_path);
- foreach my $noeud ( @nodes) {
- # Initialisation du chemin XPath relatif du noeud "data" contenant
- # la forme correspondant au premier élément du motif
- # Ce chemin est relatif au premier noeud "element" du bloc retourné
- # et pointe sur le troisième noeud "data" fils du noeud "element"
- # en l'identifiant par la valeur "string" de son attribut "type"
- my $form_xpath="";
- $form_xpath="./data[\@type=\"string\"]";
- # Initialisation du compteur pour la boucle d'éxtraction des formes correspondants
- # aux éléments suivants du motif
- my $following=0;
- # Recherche du noeud data contenant la forme correspondant au premier élément du motif
- # au moyen de la fonction "find" qui prend pour arguments:
- # 1. le chemin XPath relatif du noeud "data"
- # 2. le noeud en cours de traitement dans cette boucle foreach
- # la fonction "find" retourne par défaut une liste de noeuds, dans notre cas cette liste
- # ne contient qu'un seul élément que nous récupérons avec la fonction "get_node"
- # enfin nous en imprimons le contenu textuel au moyen de la méthode string_value
- print MATCHFILE $xpc->findvalue($form_xpath,$noeud);
- # Boucle d'éxtraction des formes correspondants aux éléments suivants du motif
- # On descend dans chaque noeud element du bloc
- while ( $following < $#tokens) {
- # Incrémentation du compteur $following de cette boucle d'éxtraction des formes
- $following++;
- # Construction du chemin XPath relatif du noeud "data" contenant
- # la forme correspondant à l'élément suivant du motif
- # Notez bien l'utilisation du compteur $folowing tant dans la condition de la boucle ci-dessus
- # que dans la construction du chemin relatif XPath
- my $following_elmt="following-sibling::element[".$following."]";
- $form_xpath=$following_elmt."/data[\@type=\"string\"]";
- # Impression du contenu textuel du noeud data contenant la forme correspondant à l'élément suivant du motif
- print MATCHFILE " ",$xpc->findvalue($form_xpath,$noeud);
- # Incrémentation du compteur $following de cette boucle d'éxtraction des formes
- # $following++;
- }
- print MATCHFILE "\n";
- }
- # Fermeture du fichiers de motifs
- close(MATCHFILE);
- }
#/usr/bin/perl <<DOC; Nom : Rachid Belmouhoub Avril 2012 usage : perl bao3_rb_new.pl fichier_tag fichier_motif DOC use strict; use utf8; use XML::LibXML; # Définition globale des encodage d'entrée et sortie du script à utf8 binmode STDIN, ':encoding(utf8)'; binmode STDOUT, ':encoding(utf8)'; # On vérifie le nombre d'arguments de l'appel au script ($0 : le nom du script) if($#ARGV!=1){print "usage : perl $0 fichier_tag fichier_motif";exit;} # Enregistrement des arguments de la ligne de commande dans les variables idoines my $tag_file= shift @ARGV; my $patterns_file = shift @ARGV; # création de l'objet XML::XPath pour explorer le fichier de sortie tree-tagger XML my $xp = XML::LibXML->new(XML_LIBXML_RECOVER => 2); $xp->recover_silently(1); my $dom = $xp->load_xml( location => $tag_file ); my $root = $dom->getDocumentElement(); my $xpc = XML::LibXML::XPathContext->new($root); # Ouverture du fichiers de motifs open(PATTERNSFILE, $patterns_file) or die "can't open $patterns_file: $!\n"; # lecture du fichier contenant les motifs, un motif par ligne (par exemple : NOM ADJ) while (my $ligne = <PATTERNSFILE>) { # Appel à la procédure d'extraction des motifs &extract_pattern($ligne); } # Fermeture du fichiers de motifs close(PATTERNSFILE); # routine de construction des chemins XPath sub construit_XPath{ # On récupère la ligne du motif recherché my $local_ligne=shift @_; # initialisation du chemin XPath my $search_path=""; # on supprime avec la fonction chomp un éventuel retour à la ligne chomp($local_ligne); # on élimine un éveltuel retour chariot hérité de windows $local_ligne=~ s/\r$//; # Construction au moyen de la fonction split d'un tableau dont chaque élément a pour valeur un élément du motif recherché my @tokens=split(/ /,$local_ligne); # On commence ici la construction du chemin XPath # Ce chemin correspond au premier noeud "element" de l'arbre XML qui répond au motif cherché $search_path="//element[contains(data[\@type=\"type\"],\"$tokens[0]\")]"; # Initialisation du compteur pour la boucle de construction du chemin XPath my $i=1; while ($i < $#tokens) { $search_path.="[following-sibling::element[1][contains(data[\@type=\"type\"],\"$tokens[$i]\")]"; $i++; } my $search_path_suffix="]"; # on utilise l'opérateur x qui permet de répéter la chaine de caractère à sa gauche autant de fois que l'entier à sa droite, # soit $i fois $search_path_suffix $search_path_suffix=$search_path_suffix x $i; # le chemin XPath final $search_path.="[following-sibling::element[1][contains(data[\@type=\"type\"],\"".$tokens[$#tokens]."\")]" .$search_path_suffix; # print "$search_path\n"; # on renvoie à la procédure appelante le chein XPath et le tableau des éléments du motif return ($search_path,@tokens); } # routine d'extraction du motif sub extract_pattern{ # On récupère la ligne du motif recherché my $ext_pat_ligne= shift @_; # Appel de la fonction construit_XPath pour le motif lu à la ligne courrante du fichier de motif my ($search_path,@tokens) = &construit_XPath($ext_pat_ligne); # définition du nom du fichier de résultats pour le motif en utilisant la fonction join my $match_file = "res_extract-".join('_', @tokens).".txt"; # Ouverture du fichiers de résultats encodé en UTF-8 open(MATCHFILE,">:encoding(UTF-8)", "$match_file") or die "can't open $match_file: $!\n"; # création de l'objet XML::XPath pour explorer le fichier de sortie tree-tagger XML # Parcours des noeuds du ficher XML correspondant au motif, au moyen de la méthode findnodes # qui prend pour argument le chemin XPath construit précédement # avec la fonction "construit_XPath" my @nodes=$root->findnodes($search_path); foreach my $noeud ( @nodes) { # Initialisation du chemin XPath relatif du noeud "data" contenant # la forme correspondant au premier élément du motif # Ce chemin est relatif au premier noeud "element" du bloc retourné # et pointe sur le troisième noeud "data" fils du noeud "element" # en l'identifiant par la valeur "string" de son attribut "type" my $form_xpath=""; $form_xpath="./data[\@type=\"string\"]"; # Initialisation du compteur pour la boucle d'éxtraction des formes correspondants # aux éléments suivants du motif my $following=0; # Recherche du noeud data contenant la forme correspondant au premier élément du motif # au moyen de la fonction "find" qui prend pour arguments: # 1. le chemin XPath relatif du noeud "data" # 2. le noeud en cours de traitement dans cette boucle foreach # la fonction "find" retourne par défaut une liste de noeuds, dans notre cas cette liste # ne contient qu'un seul élément que nous récupérons avec la fonction "get_node" # enfin nous en imprimons le contenu textuel au moyen de la méthode string_value print MATCHFILE $xpc->findvalue($form_xpath,$noeud); # Boucle d'éxtraction des formes correspondants aux éléments suivants du motif # On descend dans chaque noeud element du bloc while ( $following < $#tokens) { # Incrémentation du compteur $following de cette boucle d'éxtraction des formes $following++; # Construction du chemin XPath relatif du noeud "data" contenant # la forme correspondant à l'élément suivant du motif # Notez bien l'utilisation du compteur $folowing tant dans la condition de la boucle ci-dessus # que dans la construction du chemin relatif XPath my $following_elmt="following-sibling::element[".$following."]"; $form_xpath=$following_elmt."/data[\@type=\"string\"]"; # Impression du contenu textuel du noeud data contenant la forme correspondant à l'élément suivant du motif print MATCHFILE " ",$xpc->findvalue($form_xpath,$noeud); # Incrémentation du compteur $following de cette boucle d'éxtraction des formes # $following++; } print MATCHFILE "\n"; } # Fermeture du fichiers de motifs close(MATCHFILE); }
Ao invés de utilizar um script em Perl, nós podemos também utilizar XPATH para extrair as sequências buscadas.
Para criar uma página HTML que exiba as sequências, nós podemos utilizar xsltproc como no seguinte comando:
xsltproc stylesheet.xsl xml_file.xml > sequence.html
Esta folha de estilo permite a extração de todos as sequências "substantivo-preposição", utilizando XPATH.
- <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
- <xsl:output method="html"/>
- <xsl:template match="/">
- <html>
- <body bgcolor="#81808E">
- <table align="center" bgcolor="white" border="1" bordercolor="#3300FF" width="50%">
- <tr bgcolor="black">
- <td valign="top" width="90%">
- <font color="white">
- <h1>Extraction de patron
- <font color="red">
- <b>NOM</b></font>
- <xsl:text/>
- <font color="blue">
- <b>PRP</b>
- </font>
- <xsl:text/>
- <font color="red">
- <b>NOM</b>
- </font>
- </h1>
- </font>
- </td>
- </tr>
- <tr>
- <td>
- <blockquote>
- <xsl:apply-templates select="PARCOURS/ETIQUETAGE/file"/>
- </blockquote>
- </td>
- </tr>
- </table>
- </body>
- </html>
- </xsl:template>
- <xsl:template match="file">
- <xsl:for-each select="element">
- <xsl:if test="(./data[contains(text(),'NOM')])">
- <xsl:variable name="p1" select="./data[3]/text()"/>
- <xsl:if test="following-sibling::element[1][./data[contains(text(),'PRP')]]">
- <xsl:variable name="p2" select="following-sibling::element[1]/data[3]/text()"/>
- <xsl:if test="following-sibling::element[2][./data[contains(text(),'NOM')]]">
- <xsl:variable name="p3" select="following-sibling::element[2]/data[3]/text()"/>
- <font color="red">
- <xsl:value-of select="$p1"/>
- </font>
- <xsl:text/>
- <font color="blue">
- <xsl:value-of select="$p2"/>
- </font>
- <xsl:text/>
- <font color="red">
- <xsl:value-of select="$p3"/>
- </font>
- <br/>
- <xsl:text/>
- </xsl:if>
- </xsl:if>
- </xsl:if>
- </xsl:for-each>
- </xsl:template>
- </xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html"/> <xsl:template match="/"> <html> <body bgcolor="#81808E"> <table align="center" bgcolor="white" border="1" bordercolor="#3300FF" width="50%"> <tr bgcolor="black"> <td valign="top" width="90%"> <font color="white"> <h1>Extraction de patron <font color="red"> <b>NOM</b></font> <xsl:text/> <font color="blue"> <b>PRP</b> </font> <xsl:text/> <font color="red"> <b>NOM</b> </font> </h1> </font> </td> </tr> <tr> <td> <blockquote> <xsl:apply-templates select="PARCOURS/ETIQUETAGE/file"/> </blockquote> </td> </tr> </table> </body> </html> </xsl:template> <xsl:template match="file"> <xsl:for-each select="element"> <xsl:if test="(./data[contains(text(),'NOM')])"> <xsl:variable name="p1" select="./data[3]/text()"/> <xsl:if test="following-sibling::element[1][./data[contains(text(),'PRP')]]"> <xsl:variable name="p2" select="following-sibling::element[1]/data[3]/text()"/> <xsl:if test="following-sibling::element[2][./data[contains(text(),'NOM')]]"> <xsl:variable name="p3" select="following-sibling::element[2]/data[3]/text()"/> <font color="red"> <xsl:value-of select="$p1"/> </font> <xsl:text/> <font color="blue"> <xsl:value-of select="$p2"/> </font> <xsl:text/> <font color="red"> <xsl:value-of select="$p3"/> </font> <br/> <xsl:text/> </xsl:if> </xsl:if> </xsl:if> </xsl:for-each> </xsl:template> </xsl:stylesheet>
Esta folah de estilos permite a extração de todas as sequências "substantivos-adjetivo", utilizando XPATH.
- <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
- <xsl:output method="html"/>
- <xsl:template match="/">
- <html>
- <body bgcolor="#81808E">
- <table align="center" bgcolor="white" border="1" bordercolor="#3300FF" width="50%">
- <tr bgcolor="black">
- <td valign="top" width="90%">
- <font color="white">
- <h1>Extraction de patron
- <font color="red">
- <b>NOM</b></font>
- <font color="blue">
- <b>ADJ</b>
- </font>
- </h1>
- </font>
- </td>
- </tr>
- <tr>
- <td>
- <blockquote>
- <xsl:apply-templates select="./PARCOURS/ETIQUETAGE/file/element"/>
- </blockquote>
- </td>
- </tr>
- </table>
- </body>
- </html>
- </xsl:template>
- <xsl:template match="element">
- <xsl:choose>
- <xsl:when test="(./data[contains(text(),'NOM')]) and (following-sibling::element[1][./data[contains(text(),'ADJ')]])">
- <font color="red">
- <xsl:value-of select="./data[3]"/>
- </font>
- <xsl:text/>
- </xsl:when>
- <xsl:when test="(./data[contains(text(),'ADJ')]) and (preceding-sibling::element[1][./data[contains(text(),'NOM')]])">
- <font color="blue">
- <xsl:value-of select="./data[3]"/>
- </font>
- <br/>
- </xsl:when>
- </xsl:choose>
- </xsl:template>
- </xsl:stylesheet>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html"/> <xsl:template match="/"> <html> <body bgcolor="#81808E"> <table align="center" bgcolor="white" border="1" bordercolor="#3300FF" width="50%"> <tr bgcolor="black"> <td valign="top" width="90%"> <font color="white"> <h1>Extraction de patron <font color="red"> <b>NOM</b></font> <font color="blue"> <b>ADJ</b> </font> </h1> </font> </td> </tr> <tr> <td> <blockquote> <xsl:apply-templates select="./PARCOURS/ETIQUETAGE/file/element"/> </blockquote> </td> </tr> </table> </body> </html> </xsl:template> <xsl:template match="element"> <xsl:choose> <xsl:when test="(./data[contains(text(),'NOM')]) and (following-sibling::element[1][./data[contains(text(),'ADJ')]])"> <font color="red"> <xsl:value-of select="./data[3]"/> </font> <xsl:text/> </xsl:when> <xsl:when test="(./data[contains(text(),'ADJ')]) and (preceding-sibling::element[1][./data[contains(text(),'NOM')]])"> <font color="blue"> <xsl:value-of select="./data[3]"/> </font> <br/> </xsl:when> </xsl:choose> </xsl:template> </xsl:stylesheet>
Scripts baseados a partir dos scripts dos professores para melhorar a extração dos padrões morfosintáticos dos resultados do TreeTagger e Cordial.
Em aula nós vimos três maneiras de extrair padrões as frases desejadas utilizando Perl. Esses três scripts funcionam de maneira similar incorporando os padrões desejadas nos scripts e buscando um único padrão.
Nós propomos aqui dois scripts muito similares que nós mesmos produzimos. Eles são diferentes daquele produzidos pelos professores pelo fato de nos permitir a busca por um número ilimitado de padrões independentemente do tamanho do padrão.
- use strict;
- use warnings;
- #--------------------------------------------------------------
- # This script allows the user to search for as many morphosyntactic patterns
- # (of any/varying length) as desired from the Cordial results of tool 2
- # usage: perl ourversion1.pl patron_test.txt
- #--------------------------------------------------------------
- open(FILE,"$ARGV[0]"); # the cordial tagged text
- open(FILE2,"$ARGV[1]"); # the list of patterns
- #--------------------------------------------------------------
- # the patterns searched for are in the file patron_test.txt
- #--------------------------------------------------------------
- my @lignes = <FILE>;
- my @patrons = <FILE2>;
- close(FILE);
- close(FILE2);
- while (@lignes) {
- my $ligne = shift(@lignes);
- chomp $ligne;
- for (my $i = 0; $i < scalar@patrons; $i++) {
- my $sequence = "";
- my $forme = "";
- my $longueur = 0;
- my @split_patrons = split(' ', @patrons[$i]);
- if ($ligne =~ /^([^\t]+)\t[^\t]+\t$split_patrons[0].*/) {
- $forme = $1;
- $sequence .= $forme;
- $longueur = 1;
- for (my $j = 1; $j < scalar@split_patrons; $j++) {
- if ($lignes[$j-1] =~ /^([^\t]+)\t[^\t]+\t$split_patrons[$j].*/) {
- $forme = $1;
- $sequence .= " " . $forme;
- $longueur++;
- }
- }
- }
- if ($longueur == scalar@split_patrons) {
- print "\n[" . $sequence . "]\n";
- }
- }
- }
- close FILE;
- close FILE2;
use strict; use warnings; #-------------------------------------------------------------- # This script allows the user to search for as many morphosyntactic patterns # (of any/varying length) as desired from the Cordial results of tool 2 # usage: perl ourversion1.pl patron_test.txt #-------------------------------------------------------------- open(FILE,"$ARGV[0]"); # the cordial tagged text open(FILE2,"$ARGV[1]"); # the list of patterns #-------------------------------------------------------------- # the patterns searched for are in the file patron_test.txt #-------------------------------------------------------------- my @lignes = <FILE>; my @patrons = <FILE2>; close(FILE); close(FILE2); while (@lignes) { my $ligne = shift(@lignes); chomp $ligne; for (my $i = 0; $i < scalar@patrons; $i++) { my $sequence = ""; my $forme = ""; my $longueur = 0; my @split_patrons = split(' ', @patrons[$i]); if ($ligne =~ /^([^\t]+)\t[^\t]+\t$split_patrons[0].*/) { $forme = $1; $sequence .= $forme; $longueur = 1; for (my $j = 1; $j < scalar@split_patrons; $j++) { if ($lignes[$j-1] =~ /^([^\t]+)\t[^\t]+\t$split_patrons[$j].*/) { $forme = $1; $sequence .= " " . $forme; $longueur++; } } } if ($longueur == scalar@split_patrons) { print "\n[" . $sequence . "]\n"; } } } close FILE; close FILE2;
Uma segunda opção:
- #! /usr/bin/perl
- use strict;
- open(PATRONS, "$ARGV[0]");
- open(CORDIAL, "$ARGV[1]");
- open(CORDIAL_BKP, "$ARGV[1]");
- # créer fichier de résultats
- open my $final_result, '>>', "results.txt";
- my $terme;
- my @tags;
- # lire lignes du fichier de patrons
- while(chomp($terme=<PATRONS>)){
- # séparer les patrons de la ligne lue
- @tags = split(" ", $terme);
- my @LISTE;
- # lire le fichier étiquetté
- while(@LISTE = split(/\t/, <CORDIAL>)){
- # comparer les patrons du texte avec la patrons recherché
- if($LISTE[2] =~ m/$tags[0]/){
- # repérer position où le premier patron a été trouvé
- my $position = tell(CORDIAL);
- # continuer lecture à partir de $position
- seek(CORDIAL_BKP, $position, 0);
- my $compteur = 0;
- my $result="";
- # lire la séquence de patrons
- foreach my $tag (@tags){
- if($LISTE[2]=~ m/$tag/){
- # stocker résultat
- $result .= $LISTE[0]." ";
- # lire ligne suivant
- @LISTE = split(/\t/, <CORDIAL_BKP>);
- $compteur++;
- # si vrai, l`analyse est finie
- if($compteur == @tags){
- # écrire résultat
- print $final_result $result."\n";
- }
- }
- }
- }
- }
- seek(CORDIAL, 0, 0);
- }
- close(CORDIAL);
- close(PATRONS);
#! /usr/bin/perl use strict; open(PATRONS, "$ARGV[0]"); open(CORDIAL, "$ARGV[1]"); open(CORDIAL_BKP, "$ARGV[1]"); # créer fichier de résultats open my $final_result, '>>', "results.txt"; my $terme; my @tags; # lire lignes du fichier de patrons while(chomp($terme=<PATRONS>)){ # séparer les patrons de la ligne lue @tags = split(" ", $terme); my @LISTE; # lire le fichier étiquetté while(@LISTE = split(/\t/, <CORDIAL>)){ # comparer les patrons du texte avec la patrons recherché if($LISTE[2] =~ m/$tags[0]/){ # repérer position où le premier patron a été trouvé my $position = tell(CORDIAL); # continuer lecture à partir de $position seek(CORDIAL_BKP, $position, 0); my $compteur = 0; my $result=""; # lire la séquence de patrons foreach my $tag (@tags){ if($LISTE[2]=~ m/$tag/){ # stocker résultat $result .= $LISTE[0]." "; # lire ligne suivant @LISTE = split(/\t/, <CORDIAL_BKP>); $compteur++; # si vrai, l`analyse est finie if($compteur == @tags){ # écrire résultat print $final_result $result."\n"; } } } } } seek(CORDIAL, 0, 0); } close(CORDIAL); close(PATRONS);
Padrões utilizadas para a extração
Nós utilizamos diferentes padrões contendo ":" . Exemplo de alguns:
NPMS PCTFORTE NCMS PREP ADJIND NCMIN
VINF DETDMS NCMS PCTFORTE DETDPIG NCFP DETDMS ADJNUM NCMIN
NPI PCTFORTE DETDMS NCMS ADV VINDP3S ADV COO VINDP3S
A lista completa pode ser vista aqui.
Padrão usado: N[A-Z]+ ADJ[A-Z]+
Padrão usado: N[A-Z]+ PREP DET[A-Z]+ N[A-Z]+
Padrão usado: .*?que.*
Frases Extraídas
Diferentes padrões contendo ":" foram utilizados. Alguns exemplos:
NPMS PCTFORTE NCMS PREP ADJIND NCMIN
VINF DETDMS NCMS PCTFORTE DETDPIG NCFP DETDMS ADJNUM NCMIN
NPI PCTFORTE DETDMS NCMS ADV VINDP3S ADV COO VINDP3S
A lista completa pode ser vista aqui.
Lista de resultados com ":" .
Padrão utilizado: N[A-Z]+ ADJ[A-Z]+
Lista de resultados SUBSTANTIVO-ADJETIVO.
Padrão utilizado: N[A-Z]+ PREP DET[A-Z]+ N[A-Z]+
Lista de resultados SUBSTANTIVO-PREPOSIÇÃO-ARITGO-SUBSTANTIVO.
Padrão usado: .*?que.*
Lista de resultados VERBO-CONJUNÇÃO.
Como criar gráficos
O projeto Caixa de Ferramentas chega ao fim e, para fechar essa série de tratamentos, nós vamos construir alguns gráficos.
A Ferramenta 4 utiliza um programa externo desenvolvido para Windows que permite criar gráficos, utilizando os resultado da Ferramenta 3. Esse gráficos nos auxiliam a ter uma representação visual dos padrões encontrados nos texto.
A construção desses gráfigo tem o objetivo de ilustrar o comportamento de um token e, ou, de um tipo morfosintático específico para os quais nós fizemos suposição linguísticas.
Este tipo de representação visual nos permit ter uma noção mais clara sobre como os padrões se articulam entre eles. Nós podemos, por exemplo, utilizar a representação gráfica para destacar as relações mantidas por uma dada forma em níveis sintagmáticos e pragmáticos.
Tomamos como exemplo os gráficos abaixo confeccionados a partir de dados extraídos do tema política. Nós escolhemos enunciados onde o nome do presidente François Hollande aparece. Para facilitar a visualização e a compreenção do gráfico, nos utilizamos um número reduzido de frases.
As setas em vermelho indicam exemplos de enunciados negativos, enquanto que as setas verdes indicam enunciados positvos. A seta roxa indica uma possível transição no eixo pragmático.
Uma breve análise do gráfico é suficiente para nos indicar construções sintaximente interessantes.
Por exemplo, nós podemos observar que as mudanças no eixo paradigmático podem criar enunciados estranhos, mas não agramaticais.
Nós podemos nos divertir, criando novos enunciados seguindo o percurso proposto pelas setas. Basta mudar as direções quando encontramos um bifurcação.
Obs.: Os enunciados acima foram produzido a título meramente ilustrativo e não exprimem nenhum posição política.
Esta experiência não tem o mesmo efeito no eixo sintagmático. A inversão das formas vizinhas nesse eixo ou cria enunciados agramaticais ou enunciados semanticamente diferente.
Isso se explica pelo fato de que construções paralelas no eixo paradigmático frequentemente pertence a uma mesma classe gramatical.
Na representação gráfica, esse tipo de estrutura se encontra alinhada com setas que partem na mesma direção. Como nós podemos ver nos exemplos abaixo.
É preciso notar que um mesmo alinhamento paradigmático pode também conter elementos de tipos distintos e, neste caso, nenhuma mudança é possível.
Por exemplo:
*Como nem todos os integrantes usam Windows, nós utilizamos o programa comWine.
SUBSTANTIVO ADJETIVO
Nós decidimos executar a CdF3 para os textos do tema INTERNACIONAL com o padrão SUBSTANTIVO-ADJETIVO para recuperar todas as sequências morfosintáticas contendo um substantivo seguido de um adjetivo.
Em seguida dans CdF4, nós escolhemos como motivo o substantivo "crise" seguido de todos os adjetivos para criar o gráfico. Nós partimos da hipótese que, no contexo econômico atual no qual nós encontramos no mundo inteiro, nós encontraríamos muitas ocorrências do tipo "crise econônima". Como nós podemos constatar no gráfico, nós temos 8 ocorrências deste sintagma no tema INTERNACIONAL. O que permanece muito baixo em relação ao resultado de "crise ukranienne". Isso indica a importância dos eventos ocorridos em 2014 na Ucrânia.
No entanto, mesmo sem observar o contexto no qualo mundo estava politica e economicamente, nós nos damos conta que frequentemente nós encontramos "crise" + nacionalidade do que "crise économique", como nós esperávamos. Finalmente, a crise é mais frequentemente designada ao local onde ela ocorre e o contexto textual determina de qual tipo de crise se trata. Porém, de acordo com os resultados encontrados, praticamente todos os sintagmas encontrados fazem referência a uma crise política ou econômica.
Entretanto, a supresa foi encontrar 4 ocorrências de "crise cardiaque" no nosso gráfico. Nós esperávamos encontrar algo ligado ao contexto médico nos resultados. Sem verificar o corpus e se baseando somente nos dados fornecidos pelo gráficos, nós podemos supor que algum personagem político importante de nível internacional tenha tido um ataque cardíaco.
Nós temos igualmente três ocorrências do motivo no plural ("crises"), mas que à priori, não fazem parte do contexto econômico. O contexto médico ("epidemiológico") e talvez social ("humanitário") parecem ser os contexto que aparecem através do sintagmas. Porém, como as ocorrência no plural não são significativas para um ano inteiro, nós pensamos que isto não necessita uma análise mais profunda.
SUBSTANTIVO-PREPOSIÇÃO-ARTIGO-SUBSTANTIVO
Com o motivo direito.*, nós queríamos chegar ao contexto político/legislativo do corpus para o tema INTERNACIONAL. Nós constatamos com isso que o sintagma que o sintagma "droit de l'homme" aparece 41 vezes (se não não fizermos a distinção entre Homme e homme). A maioria dos sintagmas encontrados em torno desse motivo possuem a palavras "droit(s)" em primeiro como "droit à" ou "droit de" seguido de outros tipos. Entretanto, encontramoss algumas ocorrências que ela se encontra no fim do sintagma como "être dans son drois".
Nós percebemos que no primeiro caso, os sintagmas fazem referência a algo legislativo, indicando leis que já foram votadas ou estão em discussão. Enquanto que no segundo caso, as referências são feitas a um contexto político com situação onde há uma luta ou mobilizção para se alcançar aos direitos.
PONTUAÇÃO FORTE ":"
Nós percebemos o site do Le Monde um padrão que indicaria fortes candidatos a serem palavras-chave. Trata-se de frases contendo a pontução forte ":".
Como nós podemos observar, esse tipo de construção é muito frequente no Le Monde. Na verdade, esta estrutura de frase [sintagma nominal] ':' [sintagma nominal][sintagama]* é uma marca característica do registro jornalístico para criar títulos.
Veja alguns exemplos da mesma estrutura encontra outros periódicos franceses extraídos no mesmo dia.
Nós podemos observar que algumas reportagens reutilizam quase o mesmo título, com a mesma estrutura.
Libération
"Egypt: l'ex-président islamiste Mohamed Morsi condamné à mort"
La Tribune
"Egypt: l'ex-président islamiste Mohamed Morsi condamné à mort"
Le Figaro
"Egypt: l'ex-président Mohamed Morsi condamné à mort"
Métro News
"Egypt: Mohamed Morsi condamné à mort"
Não trata de uma falta de criativade jornalística, mas sim de uma técnica refinada para suscitar no leito o desejo de ler o texto em questão. de saber mais sobre os fatos aludidos pelo título. Na verdade, o título nos fornece os tópicos principais do assunto tratado, deixando uma lacuna de informação que só pode ser preenchida quando nós lemos a reportagem. Por exemplo, a partir dos títulos dos exemplos acima, nós podemos saver o local onde se passam os fatos e que a pessoas que lhes é submetida.
No Egito, Mohamed Morsi foi condenado a pena de morte. Mediante a essa informação o leitor pode se perguntar: "Por que razão?" "Quando será a condenação" Ou ainda: "Quem é Mohamed Morsi?"
Ce type de phrase fournit l'essenciel sans dire les "pourquoi", "quand", "qui", "où", etc. Pour nous cet essenciel est très important, puisqu'il peut être utiliser, par exemple, par des système de réfférencement (SEO). Este tipo de frase fornece o essencial sem dizer os "porquês", "quando", "quem", "onde", etc. Para nós esse tipo de informação essencial é muito importante, pois ele pode ser utilizado, por exemplo, por sistemas de otimização de motores de busca (SEO)
No Cordial o símbolo ":" é marcado com uma pontução forte, assim como ";", "!", "?" e ".". Nesse sentido, nós percebemos que uma busca simples por N[A-Z]+ PCTFORTE N[A-Z]+ V[A-Z]+ PREP N[A-Z]+
Poderia fornecido vários enunciados como:
Para contornar este problema e tentar descobrir se existem estruturas recorrentes para este tipo de frase, nós criamos um script em Python para nos ajudar com essa tarefa. O objetivo do programa é ler um conjunto de arquivo etiquetados, buscando seja "tags" ou "tokens" específicos fornecidos pelo utilizador. Como resultado, o programa produz um arquivo contendo padrões de frases que contenham o token ou o patrão escolhido.
Dans notre cas, nous avons cherché des énoncés qui contiennent le token ':' pour tous les fichiers de toutes les rubrique étiquettés par Cordial, à l'execption du fichier CINEMA.cnr. Car, nous ce fichier serait utilisé pour essayer la pertinence des patrons fournis par notre script. Si le fichier CINEMA.cnr avait aussi été lu par Trouver_Patrons.py, le résultat de notre recherche serait dénaturé car, les patrons dans le fichier de sortie inclueraient ceux de CINEMA.cnr. Donc, l'exclusion de fichier étiquété qui nous intéresse du groupe de fichiers à être analysés avec Trouver_Patrons.py est une manière de créer une sorte de training corpus. No nosso caso, nós buscamos frases que contivessem o token ":" em todos os arquivos dos temas etiquetados pelo Cordial, com exceção do arquivo CINEMA.cnr. Pois, esse arquivo seria utilizado para testar a pertinência dos padrões fornecidos pelos script. Caso o arquivo CINEMA.cnr tivesse também sido lido pelo script Trouver_Patrons.py, o resultado da nossa pesquisa seria desvirtuado, pois os padrões do resultado já incluiriam todos os padrẽos presentes em CINEMA.cnr. Portanto, a exclusão do arquivo etiquetado que nos interessa do grupo de arquivos a serem analizados por Trouver_Patrons.py é uma maneira de criar algo como o um corpus de treinamento (training corpus).
Seguem abaixo os resultado (encontrados com Trouver_Patrons.py):
Tema Cinema: total de número de frases - 1927 frases
Verdeiro Positivo | 91 |
Falso Positivo | 19 |
Verdadeiro Negativo | 1836 |
Falso Negativo | 5 |
Abrangência | 0,947 | 94% |
Precisão | 0,827 | 82% |
Medida-F | 0,87 | 87% |
Tema Política : total do número de frase - 6781 frases
Verdadeiro Positivo | 245 |
Falso Positivo | 10 |
Verdadeiro Negativo | 11721 |
Falso Negativo | 1004 |
Abrangência | 0,96 | 96% |
Precisão | 0,19 | 19% |
A partir desse resultados, nós acreditamos que, apesar da variedade de formas, é possível identificar certos tipos frase. Tendo em vista que nas frases possedendo esse tipo de estrutura contêm palavras-chave sua identificação pode ser de grande utilidade.
Segue abaixo os gráficos criados após a utilização do script para o tema CINEMA. Afim de facilitar a leitura a compreenção do gráfico, o número de frases foi reduzido:
Obs.: o símbolo ":" é representado pelo token 'pct'
Exemplo de algumas enunciados extraídos com o o script de CdF3, utilizando padrões produzido pelo script Trouver_Patrons.py:
As palavras-chave:
A palavras ditas semanticamente vazias possuem muitas ocorrências. No gráficos isso representa muitos nós, assim como para o padrão procurado.
Segue o mesmo gráfico filtrado por uma stop-list:
Neste gráfico nós podemos observar que as palavras "cinéma" e "jury" possuem muitas conexões. Esse resultado é revelador sobre o assunto tratado pelo tema em questão - o cinema.
Para concluir, é preciso dizer que várias outras análises podem ser realizadas com os mesmo tipos de dados e de ferramentos de representação. As teorias apresentadas neste trabalho, levam em conta somente o corpus utilizado para o projet. Uma averigação mais completad exige um a mesma aplicação em corpus de mais envergadura.
CONJUNÇÃO
Nós tentamos criar um gráfico com conjunções, porém o problema é que os resultados obtidos são muito densos, pois todos as frases contendo conjunção se mostram muito engedreram sintagamas muito longos. Como nós podemos observar, nós não distinguimos claramente o resultado obtido através do gráfico. Com auxílio do nosso arquivo de resultado que contém todas as frases tendo o padrão procurados, nós recuperamos somente as frases que contêm "que". Nós temos finalmente as 5 frases a seguir:
Nós possuímos somente resultados que provêm das descrição, devido ao fato do motivo fornecido para busca e criação do gráfico. O títulos sendo frases, na maior parte do tempo, curtas, isso explica o porquê nós obtemos somente frases extraídas das descrição e o comprimento surpreendente. Porém, com frases não longas, não nos supreende o fato de não termos obtido várias vezes os mesmos segmentos. Isso significaria que nós teríamos duas vezes a mesma frase no gráfico, ou seja um repetição.
O que nós podemos concluir?
Para concluir, nós podemos dizer que há uma grande variedade de sintagmes para serem analizados nos texto do Le Monde. Nós escolhemos quatros que nós acreditamos nos daria uma grande possibilidade de resultado nos gráficos realizados.
Este tipo de análise nos dá uma grande visão sobre o assunto tratado pelo corpus, sem termos necessariamente que ler o texto. Uma vez que nós saibamos que tipo de fenômeno observar, torna-se muito mais fácil analizar e encontrar eventos similares. Isso pode ser generalizados para outros tipos de publicação. Se nós tivemos, por exemplo, observamos os textos produzidos pelo Le Figaro ou L'Humanité, emborar eles sejam jornais tão diferentes, nós seríamos capazes de analizá-los da mesma maneira.