diff --git a/REST/rWosSearchByDoi.sh b/REST/rWosSearchByDoi.sh new file mode 100755 index 0000000..128b393 --- /dev/null +++ b/REST/rWosSearchByDoi.sh @@ -0,0 +1,406 @@ +#!/bin/bash + + +# Initialisation des variables pour les options +programme=$(basename $0) +substitut=$(echo $programme | sed 's/./ /g') +version='0.3.1' +modif='25/07/2022' + +function usage +{ +echo "Usage : $programme -d (fichier|-) -r (résultats|-) [ -f champs ]* " +echo " $substitut [ -T taill ] [ -j cookie_jar ] [ -ix ] " +echo " $programme -h " +} + +function aide +{ +cat << EOT + +Usage +===== + $programme -d (fichier|-) -r (résultats|-) [ -f champs ]* + $substitut [ -j cookie_jar ] [ -ix ] + $programme -h + +Options +======= + -d indique le nom du fichier avec la liste des DOIs à chercher. Si on + a un tiret “-” en argument, la liste de DOIs est lue sur l’entrée + standard + -f limite les champs présents dans les notices téléchargées. Cette + option est répétitive (par défaut, tous les champs sont présents) + -h affiche cette aide + -i ajoute dans la réponse de l’API la liste des identifiants WoS des + notices retournées + -j indique le nom du fichier qui recevra les cookies (“cookies.txt” + -r indique le nom du fichier résultat (pour la sortie standard, utiliser + le tiret “-” comme argument de l’option) + -T indique le nombre de DOI à chercher à chaque itération (90 par défaut, + avec un maximum de 100) + -x indique que les notices doivent être en XML au lieu de JSON, le format + par défaut + +EOT + +exit 0 +} + +# Déclaration explicite des tableaux “bases” et “champs” +declare -a champs + +format='json' + +# Options +while getopts d:f:hij:r:T:x i + do + case $i in + d) dois=$OPTARG;; + f) champs+=$OPTARG;; + h) aide;; + i) recid=1;; + j) cookiejar=$OPTARG;; + r) sortie=$OPTARG;; + T) taille=$OPTARG;; + x) format='xml';; + \?) echo >&2 + usage >&2 + exit 1;; + esac + done + +# Vérification des options +if [[ -z $dois || -z $sortie ]] +then + echo "Erreur : option(s) manquante(s)" >&2 + echo "" >&2 + usage >&2 + echo "" + exit 2 +fi + +if [[ $dois = '-' ]] +then + dois='/dev/fd/0' +elif [[ ! -f $dois ]] +then + echo "Erreur : fichier \"$dois\" introuvable" >&2 + exit 3 +fi + +if [[ $sortie = '-' ]] +then + sortie='/dev/fd/1' +fi + +if [[ -z $cookiejar ]] +then + cookiejar='cookies.txt' +fi + +# Vérification de la présence des programmes +# “curl” et “jq” +for i in curl jq xmllint +do + prog=$(which $i 2> /dev/null) + if [[ -z $prog ]] + then + echo "" >&2 + echo "Erreur : programme “$i” introuvable. Vérifier \$PATH." >&2 + echo "" >&2 + exit 3 + fi +done + +# Vérification de la variable '$WOS_DELAY' +if [[ -n $WOS_DELAY && ! $WOS_DELAY =~ ^[1-9][0-9]*$ ]] +then + echo "Erreur : la valeur de la variable \$WOS_DELAY doit être un entier supérieur à 1" >&2 + exit 2 +fi + +# Définition des fichiers de sortie +out="WosApiOut.$format" +err='WosApiErr.txt' +url='https://wos-api.clarivate.com/api/wos' + +# Initialisation de la clé +if [[ -z $key ]] +then + read -t 60 -s -p "clé d‘authentification : " key + echo + if [ $? -gt 128 ] + then + echo "" >&2 + echo "Erreur : temps de réponse (60 s) dépassé " >&2 + exit 3 + fi +fi + +# Gestion des autres options +if [[ ${#champs[@]} -gt 0 ]] +then + optionView='FS' + viewField='WOS' + for item in ${champs[@]} + do + while [[ -n $item ]] + do + deb=${item%%,*} + fin=${item#*,} + viewField="$viewField+$deb" + if [[ $deb = $fin ]] + then + item="" + else + item=$fin + fi + done + done + extra="\"optionView\": \"FS\", \"viewField\": \"$viewField\"" +else + extra="\"optionView\": \"FR\"" +fi + +if [[ $recid -gt 0 ]] +then + extra="$extra, \"optionOther\": \"RI+On\"" +fi + +function requete +{ +end=$(( $3 + $2 - 1 )) +printf " -> %d - %d " $3 $end >&2 + +cat << EOT > tee search.json +{ + "databaseId": "WOS", + "lang": "en", + "usrQuery": "$1", + "count": 100, + "firstRecord": 1, + $extra +} +EOT + +if [[ $format = 'json' ]] +then + curl -X POST -d @search.json -b $cookiejar -c $cookiejar -v "$url" \ + -H "Content-Type: application/json" \ + -H "X-ApiKey: $key" 2> $err | jq . 2>> $err > $out + + cr=$? + echo "Code retour “jq” = $cr" >> $err + + if [[ $cr -gt 0 ]] + then + echo "" + echo "Erreur : la réponse de l‘API est incorrecte [code jq = $cr]" >&2 + echo "" + # nettoie + exit 6 + fi + + # Test de la réponse + msg=$(perl -ne 'print "$1" if /"message": "(.+?)"/o' $out) + if [[ -n $msg ]] + then + cod=$(perl -ne 'print "$1" if /"code": "(.+?)"/o' $out) + if [[ -n $cod ]] + then + msg="$cod: $msg" + fi + + echo " " + echo "Erreur : “$msg” " + echo " " + # nettoie + exit 5 + + else + qid=$(perl -ne 'print "$1" if /^ +"QueryID": (\d+)/o;' $out) + if [[ -n $qid ]] + then + rec=$(perl -ne 'print "$1" if /^ +"RecordsFound": (\d+)/o;;' $out) + top=$(perl -ne 'print "$1" if /^ +"RecordsSearched": (\d+)/o;;' $out) + + if [[ $rec -gt 100 ]] + then + echo " " + echo "Erreur : le nombre de réponses ($rec) est supérieur au maximum autorisé (100)" + echo " " + # nettoie + exit 7 + fi + + total=$(( $total + $rec )) + cat $out >> $sortie + fi + + fi + +elif [[ $format = 'xml' ]] +then + curl -X POST -d @search.json -b $cookiejar -c $cookiejar -v "$url" \ + -H "Content-Type: application/json" \ + -H "Accept: application/xml" \ + -H "X-ApiKey: $key" 2> $err | xmllint -format - 2>> $err > $out + + cr=$? + echo "Code retour “xmllint” = $cr" >> $err + + if [[ $cr -gt 0 ]] + then + echo "" + echo "Erreur : la réponse de l‘API est incorrecte [code xmllint = $cr]" >&2 + echo "" + nettoie + exit 6 + fi + + # Test de la réponse + msg=$(perl -ne 'chomp; $l .= $_;}{print "$1" if $l =~ m|(.+?)|;' $out) + if [[ -n $msg ]] + then + code=$(perl -ne 'chomp; $l .= $_;}{print "$1" if $l =~ m|(.+?)|;' $out) + if [[ -n $code ]] + then + msg="$code: $msg" + fi + + echo " " + echo "Erreur : “$msg” " + echo " " + nettoie + exit 5 + + else + qid=$(perl -ne 'print "$1" if m|(\d+)|;' $out) + if [[ -n $qid ]] + then + rec=$(perl -ne 'print "$1" if m|(\d+)|;' $out) + top=$(perl -ne 'print "$1" if m|(\d+)|;' $out) + + cat $out >> $sortie + fi + fi + +fi + +printf " \r" >&2 +} + +# Itéraion sur la liste des DOIs +max=${taille:-90} +delai=${WOS_DELAY:-1} +nb=0 +offset=1 +total=0 + +# Vérification des variables “$max” et “$delai” +if [[ $max -lt 1 ]] +then + echo "Erreur : le nombre de notices par itération doit être compris entre 1 et 100" >&2 + exit 4 +elif [[ $max -gt 100 ]] +then + echo "Erreur : le nombre de notices par itération ne peut dépasser 100" >&2 + exit 4 +fi + +if [[ $delai -lt 1 ]] +then + echo "Erreur : la variable \$WOS_DELAY ne peut pas valoir moins d‘une seconde" + exit 4 +fi + +SECONDS=0 + +while read x +do + nb=$(( $nb + 1 )) + + if [[ $nb -eq 1 ]] + then + liste="\\\"$x\\\"" + else + liste="$liste OR \\\"$x\\\"" + fi + + if [[ $nb -eq $max ]] + then + requete "DO=($liste)" "$nb" "$offset" + offset=$(( $offset + $nb )) + liste="" + nb=0 + + while [[ $SECONDS -lt $delai ]] + do + sleep 0.5 + done + SECONDS=0 + + fi +done < $dois + +if [[ $nb -gt 0 ]] +then + requete "DO=($liste)" "$nb" "$offset" +fi + +nb=$(( $offset + $nb - 1 )) + +if [[ $format = 'json' ]] +then + perl -ne 'if (not $m) { + if (/^( +)\{/o) { + $m = $1; + if ($ok) { + print ","; + $ok = 0; + } + print; + } + } + else { + if (/^$m/o) { + print; + $n ++; + } + else { + $ok ++ if $n; + $m = "" if /^\{/o; + } + }' $sortie | + (echo '{"Records": {"records": {"REC": ['; cat; echo ']}}}') | + jq . > tmpWos$$.json + + mv tmpWos$$.json $sortie +# offset=$(perl -ne '$nb ++ if /"UID": /o;}{print $nb;' $sortie) +else + perl -ne 'foreach $rec (m|()|go) { + print "$rec\n"; + }' $sortie | + (echo ''; cat; echo '') | + xmllint -format - > tmpWos$$.xml + + mv tmpWos$$.xml $sortie +# offset=$(perl -ne 'foreach $r (m|(&2 +echo " " >&2 +echo "Nombre de DOIs cherchés : $nb" >&2 +(echo "Nombre de notices trouvées : $total / $top notices" + echo "Forfait restant : $amt" ) | + perl -pe '1 while(s/(\d)(\d\d\d)\b/$1 $2/o);' >&2 + + +exit 0 + + + +