diff --git a/outils/stats-corpus/README.md b/outils/stats-corpus/README.md index 6309f89..ac63d21 100644 --- a/outils/stats-corpus/README.md +++ b/outils/stats-corpus/README.md @@ -10,15 +10,20 @@ Si les fichiers XML éditeurs ont été extraits, il permet aussi de vérifier s’ils ont ou non les documents sous forme de texte structuré. -Le résultat comprend, en plus de l’en-tête, une ligne par document avec des champs séparés -par des tabulations (format [TSV](https://fr.wikipedia.org/wiki/Tabulation-separated_values)) ou des points-virgules (format [CSV](https://fr.wikipedia.org/wiki/Comma-separated_values)). +Le résultat peut être donné : + + * soit avec une ligne par document et des champs séparés par des tabulations (format [TSV](https://fr.wikipedia.org/wiki/Tabulation-separated_values)) + ou des points-virgules (format [CSV](https://fr.wikipedia.org/wiki/Comma-separated_values)), la première ligne étant l’en-tête donnant la liste des + champs. + * soit au format [JSON](https://fr.wikipedia.org/wiki/JavaScript_Object_Notation) où les champs multivalués sont présentés sous forme de listes. + ### Usage ``` statsCorpus.pl -l logfile -c fichier.corpus [ -r répertoireXML ] [ -s sortie ] - [ -f (tsv|csv) ] [ -x (normal|lodex) ] - statsCorpus.pl -m répertoireJSON [ -r répertoireXML ] [ -s sortie ] [ -f (tsv|csv) ] - [ -x (normal|lodex) ] + [ -f (csv|json|tsv) ] [ -x (normal|lodex) ] + statsCorpus.pl -m répertoireJSON [ -r répertoireXML ] [ -s sortie ] + [ -f (csv|json|tsv) ] [ -x (normal|lodex) ] statsCorpus.pl -h ``` @@ -27,6 +32,7 @@ -c indique le nom du fichier “.corpus” généré par le programme “harvestCorpus.pl” permettant de faire le lien entre l’identifiant ISTEX d’un document et le nom des fichiers extraits correspondants. + -f indique le format de sortie, à savoir TSV (par défaut), CSV ou JSON. -h affiche l’aide. -l indique le nom du fichier “logfile” contenant les métadonnées ISTEX au format JSON créé par l’option “-v” du programme “harvestCorpus.pl”. @@ -38,8 +44,8 @@ fichiers ZIP déchargés par le programme “harvestCorpus.pl”. Si les fichiers XML sont dans le même répertoire que les fichiers JSON, l’option “-m” seule suffit. -s indique le nom du fichier de sortie. Sinon, la sortie se fait sur la sortie standard. - Si l’extension du nom de fichier est “.tsv” ou “.csv”, le format correspondant sera - utilisé sans avoir à le spécifier à l’aide de l’option “-f”. + Si l’extension du nom de fichier est “.csv”, “.json” ou “.tsv”, le format correspondant + sera utilisé sans avoir à le spécifier à l’aide de l’option “-f”. -x étend la liste des champs affichés, soit en mode normal, soit en mode “lodex”, c'est-à-dire avec un lien, affiché en exposant, entre auteurs et affiliations. ``` @@ -68,7 +74,13 @@ ``` statsCorpus.pl -m Vieillissement -s Vieil.txt -f csv -x lodex statsCorpus.pl -m Vieillissement -s Vieil.csv -x lodex +``` +> Idem, mais avec une sortie au format [**JSON**](https://fr.wikipedia.org/wiki/JavaScript_Object_Notation). + +``` + statsCorpus.pl -m Vieillissement -s Vieil.txt -f json -x lodex + statsCorpus.pl -m Vieillissement -s Vieil.json -x lodex ``` ### Données extraites diff --git a/outils/stats-corpus/statsCorpus.pl b/outils/stats-corpus/statsCorpus.pl index a03a73d..e357904 100755 --- a/outils/stats-corpus/statsCorpus.pl +++ b/outils/stats-corpus/statsCorpus.pl @@ -19,10 +19,17 @@ my ($programme) = $0 =~ m|^(?:.*/)?(.+)|; my $substitut = " " x length($programme); -my $version = "2.1.1"; -my $dateModif = "9 Avril 2018"; +my $usage = "Usage : \n" . + " $programme -l logfile -c fichier.corpus [ -r répertoireXML ] [ -s sortie ] \n" . + " $substitut [ -f (csv|json|tsv) ] [ -x (normal|lodex) ] \n" . + " $programme -m répertoireJSON [ -r répertoireXML ] [ -s sortie ] \n" . + " $substitut [ -f (csv|json|tsv) ] [ -x (normal|lodex) ] \n". + " $programme -h \n"; -# Variables +my $version = "3.0.0"; +my $dateModif = "1 Juin 2018"; + +# Variables pour les options my $aide = 0; my $corpus = ""; my $logfile = ""; @@ -57,17 +64,13 @@ print " fichiers de métadonnées JSON correspondants aux documents extraits. \n"; print " Si les fichiers XML éditeurs ont été extraits, il permet aussi de vérifier s’ils ont ou non \n"; print " les documents sous forme de texte structuré. \n"; - print "\nUsage : \n"; - print " $programme -l logfile -c fichier.corpus [ -r répertoireXML ] [ -s sortie ]\n"; - print " $substitut [ -f (tsv|csv) ] [ -x (normal|lodex) ] \n"; - print " $programme -m répertoireJSON [ -r répertoireXML ] [ -s sortie ]\n"; - print " $substitut [ -f (tsv|csv) ] [ -x (normal|lodex) ] \n"; - print " $programme -h\n"; + print "\n"; + print $usage; print "\nOptions : \n"; print " -c indique le nom du fichier “.corpus” généré par le programme “harvestCorpus.pl” permettant \n"; print " de faire le lien entre l’identifiant ISTEX ou ARK d’un document et le nom des fichiers \n"; print " extraits correspondants.\n"; - print " -f indique le format de sortie, à savoir TSV (par défaut) ou CSV. \n"; + print " -f indique le format de sortie, à savoir TSV (par défaut), CSV ou JSON. \n"; print " -h affiche cette aide. \n"; print " -l indique le nom du fichier “logfile” contenant les métadonnées ISTEX au format JSON \n"; print " créé par l’option “-v” du programme “harvestCorpus.pl”. Par défaut, ce fichier \n"; @@ -81,8 +84,8 @@ print " fichiers ZIP déchargés par le programme “harvestCorpus.pl”. Si les fichiers XML sont \n"; print " dans le même répertoire que les fichiers JSON, l’option “-m” seule suffit. \n"; print " -s indique le nom du fichier de sortie. Sinon, la sortie se fait sur la sortie standard. \n"; - print " Si l'extension du fichier de sortie est “.tsv” ou “.csv”, le format correspondant est \n"; - print " utilisé. \n"; + print " Si l'extension du fichier de sortie est “.csv”, “.json” ou “.tsv”, le format correspondant \n"; + print " est utilisé. \n"; print " -x étend la liste des champs affichés, soit en mode normal, soit en mode “lodex”, \n"; print " c'est-à-dire avec un lien, affiché en exposant, entre auteurs et affiliations. \n"; print "\nExemples : \n"; @@ -107,7 +110,7 @@ # Test sur le format de sortie if ( $type ) { - if ( $type !~ /^[ct]sv\z/oi ) { + if ( $type !~ /^(csv|json|tsv)\z/oi ) { print STDERR "$programme : le format de fichier \"$type\" n’est pas correct !\n"; usage(4); } @@ -117,7 +120,7 @@ # Test de l’existence d’un nom de fichier de sortie # et de son extension avant ouverture de celui-ci if ( $sortie ) { - if ( $sortie =~ /\.([ct]sv)\z/oi ) { + if ( $sortie =~ /\.(csv|json|tsv)\z/oi ) { my $tmp = lc($1); if ( $type and $type ne $tmp ) { print STDERR "$programme : le format \"$type\" et l’extension \"$tmp\" ne sont pas compatible !\n"; @@ -147,9 +150,11 @@ my $entete = ""; my $format = ""; my $json = ""; -my $racine = ""; +my $nbDocs = 0; my $num = 0; +my $racine = ""; my $total = 0; +my @champs = (); my %racine = (); # Verbalisation des codes langues ISO 639-2 @@ -181,23 +186,29 @@ ); if ( $xtended ) { - $entete = "Nom de fichier\tTitre\tAuteur(s)\tAffiliation(s)\tRevue ou monographie\tISSN\te-ISSN" . - "\tISBN\te-ISBN\tÉditeur\tType de publication\tType de document\tDate de publication" . - "\tLangue(s) du document\tRésumé\tMots-clés d’auteur\tCatégories WoS\t" . - "Catégories Science-Metrix\tCatégories Scopus\tCatégories INIST\tScore qualité\t" . - "Version PDF\tXML structuré\tIdentifiant ISTEX\tARK\tDOI\tPMID"; + @champs = ("Nom de fichier", "Titre", "Auteur(s)", "Affiliation(s)", + "Revue ou monographie", "ISSN", "e-ISSN", "ISBN", "e-ISBN", + "Éditeur", "Type de publication", "Type de document", + "Date de publication", "Langue(s) du document", "Résumé", + "Mots-clés d’auteur", "Catégories WoS", "Catégories Science-Metrix", + "Catégories Scopus", "Catégories INIST", "Score qualité", + "Version PDF", "XML structuré", "Identifiant ISTEX", "ARK", + "DOI", "PMID"); } else { - $entete = "Identifiant ISTEX\tARK\tNom de fichier\tÉditeur\tScore qualité\tVersion PDF" . - "\tXML structuré\tDate de publication\tTitre\tRevue\tISSN\te-ISSN\tType de publication" . - "\tType de document\tCatégories WoS\tCatégories Science-Metrix\tCatégories Scopus\t" . - "Catégories INIST"; + @champs = ("Identifiant ISTEX", "ARK", "Nom de fichier", "Éditeur", + "Score qualité", "Version PDF", "XML structuré", + "Date de publication", "Titre", "Revue", "ISSN", + "e-ISSN", "Type de publication", "Type de document", + "Catégories WoS", "Catégories Science-Metrix", + "Catégories Scopus", "Catégories INIST"); } +my $entete = join("\t", @champs); if ( $type eq "csv" ) { print OUT "\x{FEFF}" . tsv2csv($entete) . "\n"; } -else { +elsif ( $type eq "tsv" ) { print OUT "\x{FEFF}$entete\n"; } @@ -221,9 +232,14 @@ open(TAB, "<:utf8", $corpus) or die "Erreur : Impossible d'ouvrir \"$corpus\" : $!,"; } + my $nbIds = 0; while() { + if ( m|^total +: (\d+) (/ \d+ )?documents|o ) { + $nbDocs = $1; + } if ( /^(ark|id) /o ) { chomp; + $nbIds ++; s/\r//go; # Au cas où ... my ($type, $id, $com, $nom) = split(/\s+/); if ( $type eq 'ark' and $id !~ /^ark:/o ) { @@ -233,6 +249,12 @@ } } close TAB; + if ( not $nbDocs and $nbIds ) { + $nbDocs = $nbIds + } + if ( $type eq 'json' ) { + print OUT "{\n \"total\": $nbDocs,\n \"docs\": [\n"; + } # ... avant la lecture du fichier “logRequete” if ( not -f $logfile ) { @@ -288,6 +310,12 @@ opendir(DIR, $metadata) or die "$!,"; my @fichiers = sort grep(/\.json$/, readdir DIR); closedir DIR; + + $nbDocs = $#fichiers + 1; + if ( $type eq 'json' ) { + print OUT "{\n \"total\": $nbDocs,\n \"docs\": [\n"; + } + foreach my $fichier (@fichiers) { ($racine) = $fichier =~ /^(.+)\.json\z/o; open(JSN, "<:raw", "$metadata/$fichier") or die "$!,"; @@ -302,6 +330,10 @@ close JSN; } } +if ( $type eq 'json' ) { + print OUT " ]\n}\n"; + } +close OUT; exit 0; @@ -309,11 +341,7 @@ sub usage { -print STDERR "Usage : $programme -l logfile -c fichier.corpus [ -r répertoireXML ] [ -s sortie ] \n"; -print STDERR " [ -f (tsv|csv) ] [ -x (normal|lodex) ] \n"; -print STDERR " $programme -m répertoireJSON [ -r répertoireXML ] [ -s sortie ] \n"; -print STDERR " [ -f (tsv|csv) ] [ -x (normal|lodex) ] \n"; -print STDERR " $programme -h \n"; +print STDERR $usage; exit shift; } @@ -325,6 +353,7 @@ $num ++; my $fichier = undef; my $xml = undef; +my @valeurs = (); my %hit = %{$ref}; my $id = $hit{'id'}; my $ark = $hit{'arkIstex'}; @@ -394,7 +423,11 @@ my $langues = ""; if ( defined $hit{'language'} ) { - $langues = join(" ; ", @{$hit{'language'}}); + $langues = join(" ; ", @{$hit{'language'}}) if $type ne 'json'; + $langues = \@{$hit{'language'}} if $type eq 'json'; + } +elsif ( $type eq 'json' ) { + $langues = []; } my $wos = ""; my $scienceMetrix = ""; @@ -403,21 +436,47 @@ if ( defined $hit{'categories'} ) { my %categories = %{$hit{'categories'}}; if ( defined $categories{'wos'} ) { - $wos = join(" ; ", @{$categories{'wos'}}); + $wos = join(" ; ", @{$categories{'wos'}}) if $type ne 'json'; + $wos = \@{$categories{'wos'}} if $type eq 'json'; + } + elsif ( $type eq 'json' ) { + $wos = []; } if ( defined $categories{'scienceMetrix'} ) { - $scienceMetrix = join(" ; ", @{$categories{'scienceMetrix'}}); + $scienceMetrix = join(" ; ", @{$categories{'scienceMetrix'}}) if $type ne 'json'; + $scienceMetrix = \@{$categories{'scienceMetrix'}} if $type eq 'json'; + } + elsif ( $type eq 'json' ) { + $scienceMetrix = []; } if ( defined $categories{'scopus'} ) { - $scopus = join(" ; ", @{$categories{'scopus'}}); + $scopus = join(" ; ", @{$categories{'scopus'}}) if $type ne 'json'; + $scopus = \@{$categories{'scopus'}} if $type eq 'json'; + } + elsif ( $type eq 'json' ) { + $scopus = []; } if ( defined $categories{'inist'} ) { - $inist = join(" ; ", @{$categories{'inist'}}); + $inist = join(" ; ", @{$categories{'inist'}}) if $type ne 'json'; + $inist = \@{$categories{'inist'}} if $type eq 'json'; } + elsif ( $type eq 'json' ) { + $inist = []; + } + } +elsif ( $type eq 'json' ) { + $wos = []; + $scienceMetrix = []; + $scopus = []; + $inist = []; } my $genre = ""; if ( defined $hit{'genre'} ) { - $genre = join(", ", @{$hit{'genre'}}); + $genre = join(", ", @{$hit{'genre'}}) if $type ne 'json'; + $genre = \@{$hit{'genre'}} if $type eq 'json'; + } +elsif ( $type eq 'json' ) { + $genre = []; } my $pdfVersion = ""; my $score = ""; @@ -442,19 +501,39 @@ $revue = $host{'title'} } if ( defined $host{'isbn'} ) { - $isbn = join("/", @{$host{'isbn'}}); + $isbn = join("/", @{$host{'isbn'}}) if $type ne 'json'; + $isbn = \@{$host{'isbn'}} if $type eq 'json'; + } + elsif ( $type eq 'json' ) { + $isbn = []; } if ( defined $host{'eisbn'} ) { - $eisbn = join("/", @{$host{'eisbn'}}); + $eisbn = join("/", @{$host{'eisbn'}}) if $type ne 'json'; + $eisbn = \@{$host{'eisbn'}} if $type eq 'json'; + } + elsif ( $type eq 'json' ) { + $eisbn = []; } if ( defined $host{'issn'} ) { - $issn = join("/", @{$host{'issn'}}); + $issn = join("/", @{$host{'issn'}}) if $type ne 'json'; + $issn = \@{$host{'issn'}} if $type eq 'json'; + } + elsif ( $type eq 'json' ) { + $issn = []; } if ( defined $host{'eissn'} ) { - $eissn = join("/", @{$host{'eissn'}}); + $eissn = join("/", @{$host{'eissn'}}) if $type ne 'json'; + $eissn = \@{$host{'eissn'}} if $type eq 'json'; + } + elsif ( $type eq 'json' ) { + $eissn = []; } if ( defined $host{'genre'} ) { - $dt = join(", ", @{$host{'genre'}}); + $dt = join(", ", @{$host{'genre'}}) if $type ne 'json'; + $dt = \@{$host{'genre'}} if $type eq 'json'; + } + elsif ( $type eq 'json' ) { + $dt = []; } } my $structure = "Absent"; @@ -555,7 +634,8 @@ } } } - $auteurs = join(" ; ", @names); + $auteurs = join(" ; ", @names) if $type ne 'json'; + $auteurs = \@names if $type eq 'json'; } if ( @affiliations ) { if ( $#names > 0 and $xtended eq 'lodex' ) { @@ -563,9 +643,14 @@ $affiliations[$n] = $n + 1 . ") $affiliations[$n]"; } } - $affiliations = join(" ; ", @affiliations); + $affiliations = join(" ; ", @affiliations) if $type ne 'json'; + $affiliations = \@affiliations if $type eq 'json'; } } + elsif ( $type eq 'json' ) { + $auteurs = []; + $affiliations = []; + } if ( $hit{'language'} ) { my @langues = @{$hit{'language'}}; foreach my $item (@langues) { @@ -576,17 +661,29 @@ print STDERR "Attention : pas de verbalisation pour le code langue \"$item\"\n"; } } - $langues = join(" ; ", @langues); + $langues = join(" ; ", @langues) if $type ne 'json'; + $langues = \@langues if $type eq 'json'; + } + elsif ( $type eq 'json' ) { + $langues = []; } if ( $hit{'abstract'} ) { $resume = $hit{'abstract'}; $resume =~ s/^(abstract|summary)\s*:\s*//io; } if ( $hit{'doi'} ) { - $doi = join(" ; ", @{$hit{'doi'}}); + $doi = join(" ; ", @{$hit{'doi'}}) if $type ne 'json'; + $doi = \@{$hit{'doi'}} if $type eq 'json'; + } + elsif ( $type eq 'json' ) { + $doi = []; } if ( $hit{'pmid'} ) { - $pmid = join(" ; ", @{$hit{'pmid'}}); + $pmid = join(" ; ", @{$hit{'pmid'}}) if $type ne 'json'; + $pmid = \@{$hit{'pmid'}} if $type eq 'json'; + } + elsif ( $type eq 'json' ) { + $pmid = []; } if ( $hit{'subject'} ) { my @tmp = (); @@ -597,29 +694,52 @@ } } my %tmp = (); - $motscles = join(" ; ", grep {not $tmp{$_} ++;} @tmp); - $motscles =~ s| / | ; |go; + if ( $type eq 'json' ) { + my @motscles = grep {not $tmp{$_} ++;} @tmp; + $motscles = \@motscles; + } + else { + $motscles = join(" ; ", grep {not $tmp{$_} ++;} @tmp); + } + # Pourquoi cette substitution ? + # $motscles =~ s| / | ; |go; + } + elsif ( $type eq 'json' ) { + $motscles = []; } - my $ligne = "$fichier\t$titre\t$auteurs\t$affiliations\t$revue\t$issn\t$eissn\t"; - $ligne .= "$isbn\t$eisbn\t$nom\t$dt\t$genre\t$date\t$langues\t$resume\t"; - $ligne .= "$motscles\t$wos\t$scienceMetrix\t$scopus\t$inist\t$score\t$pdfVersion"; - $ligne .= "\t$structure\t$id\t$ark\t$doi\t$pmid"; - if ( $type eq "csv" ) { - print OUT tsv2csv($ligne), "\n"; + my @valeurs = ($fichier, $titre, $auteurs, $affiliations, $revue, $issn, $eissn, + $isbn, $eisbn, $nom, $dt, $genre, $date, $langues, $resume, $motscles, + $wos, $scienceMetrix, $scopus, $inist, $score, $pdfVersion, $structure, + $id, $ark, $doi, $pmid); + if ( $type eq 'json' ) { + json(@valeurs); } else { - print OUT "$ligne\n"; + my $ligne = join("\t", @valeurs); + if ( $type eq "csv" ) { + print OUT tsv2csv($ligne), "\n"; + } + elsif ( $type eq 'tsv' ) { + print OUT "$ligne\n"; + } } } else { - my $ligne = "$id\t$ark\t$fichier\t$nom\t$score\t$pdfVersion\t$structure\t$date\t$titre"; - $ligne .= "\t$revue\t$issn\t$eissn\t$dt\t$genre\t$wos\t$scienceMetrix\t$scopus\t$inist"; - if ( $type eq "csv" ) { - print OUT tsv2csv($ligne), "\n"; + my @valeurs = ($id, $ark, $fichier, $nom, $score, $pdfVersion, $structure, $date, + $titre, $revue, $issn, $eissn, $dt, $genre, $wos, $scienceMetrix, + $scopus, $inist); + if ( $type eq 'json' ) { + json(@valeurs); } else { - print OUT "$ligne\n"; + my $ligne = join("\t", @valeurs); + if ( $type eq "csv" ) { + print OUT tsv2csv($ligne), "\n"; + } + elsif ( $type eq 'tsv' ) { + print OUT "$ligne\n"; + } } } } @@ -639,6 +759,52 @@ return join(";", @champs); } +sub json +{ +my @valeurs = @_; + +$nbDocs --; +my $nb = $#champs; +print OUT " {\n"; +foreach my $champ (@champs) { + my $valeur = shift @valeurs; + if ( ref($valeur) eq 'ARRAY' ) { + my @tmp = @{$valeur}; + print OUT " \"$champ\": [\n"; + while(my $tmp = shift @tmp) { + if ( $tmp =~ /^\d+\z/o ) { + print OUT " $tmp"; + } + else { + print OUT " \"$tmp\""; + } + print OUT "," if $#tmp > -1; + print OUT "\n"; + } + print OUT " ]"; + print OUT "," if $nb; + print OUT "\n"; + } + else { + if ( $valeur =~ /^\d+\z/o ) { + print OUT " \"$champ\": $valeur"; + } + else { + print OUT " \"$champ\": \"$valeur\""; + } + print OUT "," if $nb; + print OUT "\n"; + } + $nb --; + } +if ( $nbDocs ) { + print OUT " },\n"; + } +else { + print OUT " }\n"; + } +} + sub langues { return (