Skip to content
Snippets Groups Projects
Commit 27d18a56 authored by Rachid Aliouat's avatar Rachid Aliouat :unicorn:
Browse files

ajout du programme recup-sets-alma.pl pour recuperer les resultats d un jeu de resultats

parent 97cd6f82
No related branches found
No related tags found
No related merge requests found
API Configuration and Administration
programme recup-sets-alma.pl
Programme qui va récuperer les membres d'un sets alma. C'est à dire les résultats de recherche d'une jeu de résultat Alma.
Api utilise : Retrieve Set Members
GET /almaws​/v1​/conf​/sets​/{set_id}​/members
fichier de conf à passer en parametre
perl recup-sets-alma.pl config-test.conf
Le fichier de conf contient la cle api et le numéro de l'ensemble : set_id
api_user_conf RecupConfSandBox
api_cle_conf l8xx403e####################bcf612
set_id 123456891011213141516
fic_sortie resultats.csv
horodatage no
#!/usr/bin/perl -w
##################
# Rachid Aliouat
# Le 07/02/2023
# API Configuration and Administration
# Récupérer les résultats de recherche d'un jeu
#################
use strict;
use warnings;
use LWP::UserAgent; # bibliothèque pour les webservice
use XML::Twig; # bibliothèque pour le XML
use URI::Encode qw(uri_encode uri_decode);; #encoder decoder les URL - requiert la bibliotheque liburi-encode-perl
my $token="";
my @tab_resultats=();
my @tab_ppn=();
my $indice=0;
my $j=0;
my $nom_fic_conf="";
my $nom_fic_csv="";
my %hash_entete=(); # pour retrouver plus facilement une valeur
my @tab_entete=(); # pour parcourir dans l'ordre les colonnes
my $ligne_entete_csv="";
my $nbr_colonne=0;
my $entete_csv_deja_ecrit=0;
my $taille_lot=100; # taille d'un lot de resultat i.e "la limite"
#my $max_ppn_url = 100; # nombre max de bloc ppn dans l'url : attention une url est limitée en nombre d'octect : pas plus de 100 PPN car c'est encapsulé dans des balises XML verbeuses...
#my $compteur_ppn=0;
$nom_fic_conf=$ARGV[0];
##### LIRE LE FICHIER DE CONF
my %hash_conf=();
open (CONF, $nom_fic_conf) or die "Ouverture fichier de configuration $nom_fic_conf impossible , cause : $! \n";
print "lecture de la configuration:\n";
print "-" x 20, "\n";
my @tab_inter = <CONF>;
close(CONF);
my $i=0;
for ($i=0;$i<=$#tab_inter;$i++) {
print $tab_inter[$i];
my @ligne=split('\t',$tab_inter[$i]); # decoupage ligne
$hash_conf{$ligne[0]}=epure($ligne[1]); # alimentation de la table de hash avec la conf
}
print "-" x 20, "\n";
##### si horodatage du nom de fichier est "yes"
if ($hash_conf{'horodatage'}=~ /yes/){
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
#printf("%02d:%02d:%02d", $hour, $min, $sec);
#my $date_jour=sprintf("%02d-%02d-%04d", $mday, ($mon+1), (1900+$year));
my $date_jour=sprintf("%04d-%02d-%02d", (1900+$year),($mon+1),$mday);
print "Horodatage : $date_jour\n";
$hash_conf{'fic_sortie'}=$date_jour."-".$hash_conf{'fic_sortie'};
}
########### Appel de l'API Configuration
my $twig_rapport=XML::Twig->new( # on créer un objet TWIG dans lequel on met toute la structure XML
pretty_print => 'indented',
);
## on commence par récuperer juste le 1er resultat pour analyse : liste des noms de colonne, nombre de resultats au total
my $block_xml=get_alma_sets_by_id($hash_conf{set_id},1,0); # Appel de l'API configuraiton sur l'id du set present dans le fichier de conf
$block_xml =~/<members total_record_count=\"(\d{1,})\">/;
my $nbr_membres =$1;
$twig_rapport->parse($block_xml); # ici tout est dans la structure twig
print $twig_rapport->sprint; # affichage du contenu
print "\n###########\nIl y a $nbr_membres resultats au total à récupérer\n";
print "Liste des colonnes :\n";
aliment_tab_indices ($twig_rapport); ### Alimentation de la ligne d'entete avec les intitulé de colonne pour le CSV
### On doit boucler pour récuperer tous les résultats car il n'y a pas de notion de ResumeToken
### On va jouer avec les parametre limit(nombre de membre à renvoyer) offset (la notion de saut)
### donc on recupére les 100 premiers, puis les 100 suivant en sautant de 100 positions
### on commence par faire un calcul pour savoir combien d'appel on va faire
### $nbr_appel = $nbr_membres / 100 ==> arrondi à l'entier supérieur
my $nbr_appel = div_entier_sup($nbr_membres,100);
print "pour $nbr_membres membres, il faut $nbr_appel appel(s)\n";
#### Appels api pour recuperer tous les résultats de recherche par paquet de 100 :limit=100 et offset=$nbr
#$i=1;
my $limit=$taille_lot;
my $offset=0;
for ($i=1;$i<=$nbr_appel;$i++) {
$offset=(($i-1)*$limit);
print "Appel API $i / $nbr_appel : limit=$limit offset=$offset\n";
$block_xml=get_alma_sets_by_id($hash_conf{set_id},$limit,$offset); # Appel de l'API configuraiton sur l'id du set present dans le fichier de conf
$twig_rapport->parse($block_xml);
aliment_tab_resultats($twig_rapport);
}
################ Fonctions
########### fonction Retourne la chaine de caractère passée en paramètre en ne laissant que les caractères autorisés
sub epure {
my ($res)=@_;
$res=~ s/\n//g;
$res=~ s/\r//g;
#$res=~ s/\"//g;
return $res;
}
#### Division en arrondissant à l'entier supérieur
sub div_entier_sup {
my ($num_1,$num_2)=@_;
my $res = 0;
if(($num_1 % $num_2) == 0){
$res = $num_1 / $num_2;
}
else{
$res = int($num_1 / $num_2) + 1;
}
return($res);
}
######## Fonction alimente tableau indice de colonne pour chaque libellé de colonne car l'ordre des colonnes peut changer si on modifie le rapport analytics
sub aliment_tab_indices{
my ($twig_rapport)=@_;
my $z=0;
my $nom_col="";
my $numero_col=$z;
my $root= $twig_rapport->get_xpath('//members',0);
#print $root->sprint; # affichage du contenu
print "\n";
my @les_colonnes= $root->first_child('member')->children; ### on récuperer une table de hash de tous les "enfants" du root
foreach my $une_colonne (@les_colonnes) # liste chaque nouveaute de la liste des nouveautes
{
#print $une_colonne->name,"\n";
$nom_col=$une_colonne->name;
$numero_col=$z;
print "Colonne num $numero_col -> $nom_col\n";
$tab_entete[$numero_col]=$nom_col;
$hash_entete{$nom_col} = $numero_col;
$ligne_entete_csv.=$nom_col."\t";
#$tab_entete[$z]=$nom_col;
$z++;
$nom_col="";
}
$nbr_colonne=$z-1;
}
######## Fonction alimente tableau des resultats
sub aliment_tab_resultats{
print "\nALIMENTE TABLE\n";
my ($twig_rapport)=@_;
#print $twig_rapport->sprint;
my $root= $twig_rapport->get_xpath('//members',0);
#my $root= $twig_rapport->get_xpath('//',0);
my @les_members= $root->children;#('members'); ### on récuperer une table de hash de tous les "enfants" du root = les entrées <Row> de la racine <rowset>
#print "#########################\n";
#print "####".$root->first_child('Row')->first_child('Column12')->text()."####\n";
my $i=0;
foreach my $un_member (@les_members) # liste chaque nouveaute de la liste des nouveautes
{
#print $un_member->sprint,"\n#######\n";
for ($i=0;$i<=$#tab_entete;$i++) {
#print $tab_entete[$i]." : ";
#print $un_member->first_child($tab_entete[$i])->text();
#print "\n";
$tab_resultats[$indice][$i]=$un_member->first_child($tab_entete[$i])->text();
}
$indice++;
#print "\n";
}
}
#### Ecriture du fichier CSV en mode Ajout
print "Ecriture du fichier CSV\n";
open (FIC, ">".$hash_conf{fic_sortie}) or die "Ouverture fichier de liste exemplaire CSV impossible , cause : $! \n";
binmode(FIC, ":utf8");
print FIC "$ligne_entete_csv\n";
for ($i=0;$i<=$#tab_resultats;$i++) {
for ($j=0;$j<=$#tab_entete;$j++) {
print FIC $tab_resultats[$i][$j];
if ($j<$#tab_entete) {print FIC "\t"} # on met une tabulation sauf après la derniere colonne
}
print FIC "\n";
}
close(FIC);
############## fonction API GET pour questionner Alma API Configuration: Recuperer les données sur la base du set_id du jeu de resultat
sub get_alma_sets_by_id{
my ($set_id,$limit,$offset)=@_; # on récupére le set_id du jeu ou le offset en paramétre
print "Appel fonction GET\n ----\n$set_id\n$token\n";
print "$set_id\n";
# Creer un agent pour questionner le webservice = céer un agent c'est comme ouvrir un navigateur internet
my $ua = LWP::UserAgent->new;
$ua->agent("MyApp/0.1");
# Creer la requete
my $chaine_rq="";
print "-----appel pour $limit resultats à partir de la position $offset----\n";
$chaine_rq="https://api-eu.hosted.exlibrisgroup.com/almaws/v1/conf/sets/$set_id/members?limit=$limit&offset=$offset&apikey=".$hash_conf{api_cle_conf};
print $chaine_rq,"\n";
my $req = HTTP::Request->new(GET => $chaine_rq);
$req->content_type('application/xml');
$req->authorization_basic($hash_conf{api_user_conf}, $hash_conf{api_cle_conf}); # login + mot de passe => user_api + cle api
# Passer requete au user agent et récuperer la reponse
my $i=0;
my $max=3; #maximum de tentative
my $status="NOK";
while ($status =~ /^NOK$/){
my $res = $ua->request($req);
# Vérifier la reponse
if ($res->is_success) {
print "##############################","\n";
#print $res->content;
print "Existence notice OK pour $set_id\n";
print "##############################","\n";
$status=$res->content;
} else {
print $res->content;
print "\n############################","\n";
print $res->status_line, "\n";
print "\n############################","\n";
$i++;
if ($i==$max) {
$status="MAX"; # on force la sortie de la boucle meme si c'est pas ok
}
}
}
return $status;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment