#!/bin/bash # Initialisation des variables pour les options programme=$(basename $0) substitut=$(echo $programme | sed 's/./ /g') version='1.5.1' modif='25/07/2022' function usage { echo "Usage : $programme -s sid -q queryId -n nb_notices -r résultat " echo " $substitut [ -f champs ]* [ -t CH:(A|D) ] [ -i ] " echo " $substitut [ -o offset ] [ -T taille ] [ -j cookie_jar ] " echo " $programme -h " } function aide { cat << EOT Usage ===== $programme -s sid -q queryId -n nb_notices -r résultat $substitut [ -f champs ]* [ -t CH:(A|D) ] [ -i ] $substitut [ -o offset ] [ -t taille ] [ -j cookie_jar ] $programme -h Options ======= -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 (5 par défaut ou valeur de l’option “-n”) -j indique le nom du fichier qui recevra les cookies (“cookies.txt” par défaut) -n indique le nombre total de notices WoS à télécharger (la valeur maximale est donnée par le programme envoyant la requête à l’API WoS) -o indique à partir de quel numéro (offset), on veut télécharger les notices, en particulier pour reprendre un téléchargement après un problème de connexion (1 par défaut) -q indique le numéro de la requête “queryId” dont on veut télécharger les résultats -r indique le nom du fichier résultat (pour la sortie standard, utiliser le tiret “-” comme argument de l’option) -s indique le jeton d’authentification “SID” obtenu avec le programme d’authentification à l'API WoS -t trie les résultats sur un champ (nom abrégé à 2 majuscules) de façon croissante (A) ou décroissante (D) ou par pertinence (RS) -T indique le nombre de notices à télécharger à chaque itération (100 par défaut) N.B. : la variable d‘environnement WOS_DELAY permet de modifier le délai entre deux itérations (1 seconde par défaut). Sa valeur doit être un entier positif supérieur à 1, par ex. : “export WOS_DELAY=3” EOT exit 0 } function nettoie { if [[ -f retrieve$$.xml ]] then rm -f retrieve$$.xml fi if [[ -f tmpWos$$.xml ]] then rm -f tmpWos$$.xml fi } # Déclaration explicite des tableaux “champs” et “tri” declare -a champs # declare -a tri # Options while getopts f:hij:n:o:q:r:s:t:T: i do case $i in f) champs+=($OPTARG);; h) aide;; i) recid=1;; j) cookiejar=$OPTARG;; n) nb=$OPTARG;; o) offset=$OPTARG;; q) qid=$OPTARG;; r) sortie=$OPTARG;; s) sid=$OPTARG;; t) tri=$OPTARG;; # t) tri+=($OPTARG);; T) taille=$OPTARG;; \?) echo >&2 usage >&2 exit 1;; esac done # Vérification des options if [[ -z $sid || -z $qid || -z $nb || -z $sortie ]] then echo "Erreur : option(s) manquante(s)" >&2 echo "" >&2 usage >&2 echo "" >&2 exit 2 fi if [[ $sortie = '-' ]] then sortie='/dev/fd/1' fi if [[ -z $cookiejar ]] then cookiejar='cookies.txt' fi if [[ ! $nb =~ ^[1-9][0-9]*$ ]] then echo "Erreur : le nombre de notices (option “-n”) doit être un entier positif non nul" >&2 exit 2 fi if [[ -z $offset ]] then offset=1 else if [[ $offset =~ ^[1-9][0-9]*$ ]] then if [[ $offset -gt $nb ]] then echo "Attention : offset supérieur au nombre de notices" >&2 fi else echo "Erreur : l’offset (option “-o”) doit être un entier positif non nul" >&2 exit 2 fi fi # Vérification de la présence des programmes # “curl” et “xmllint” for i in curl 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 2 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 # Nettoyage en cas d’arrêt prématuré trap nettoie HUP INT QUIT TERM # Définition des fichiers de sortie out='WosApiOut.xml' err='WosApiErr.txt' # fonction “cherche” function cherche { end=$(( $1 + $2 - 1 )) printf " -> %d - %d " $1 $end >&2 cat << EOT > retrieve$$.xml <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <ns2:retrieve xmlns:ns2="http://woksearch.v3.wokmws.thomsonreuters.com"> <queryId>$qid</queryId> <retrieveParameters> <firstRecord>$1</firstRecord> <count>$2</count> EOT # Cas de l'option “-t” # Valeurs possibles : AU, CF, CG, CW, CV, LC, LD, PG, PY, RS, SO, TC et VL if [[ -n $tri ]] then if [[ ! $tri =~ ^(AU|CF|CG|CW|CV|LC|LD|PG|PY|SO|VL):[AD]$ && ! $tri =~ ^(RS|TC):D$ ]] then echo "Erreur : argument incorrect pour pour l’option “-t”" >&2 exit 4 fi nom=${tri%%:*} sens=${tri#*:} echo " <sortField>" >> retrieve$$.xml echo " <name>$nom</name>" >> retrieve$$.xml echo " <sort>$sens</sort>" >> retrieve$$.xml echo " </sortField>" >> retrieve$$.xml fi # Cas de l’option “-f” # Valeurs possibles : UID, pub_info, names, full_name, titles, contributor, # language, doctypes, conf_title, conf_date, conf_host, conf_locations, sponsors, # keywords, keywords_plus, abstract, addresses, organizations, reprint_contact, # email_addr, grant, fund_text, refs, address_spec, headings, subjects, identifiers, # page, book_chapters et ids if [[ ${#champs[@]} -gt 0 ]] then ns='Fields' echo " <viewField>" >> retrieve$$.xml echo " <collectionName>WOS</collectionName>" >> retrieve$$.xml for item in ${champs[@]} do while [[ -n $item ]] do deb=${item%%,*} fin=${item#*,} echo " <fieldName>$deb</fieldName>" >> retrieve$$.xml if [[ $deb = $fin ]] then item="" else item=$fin fi done done echo " </viewField>" >> retrieve$$.xml else ns='FullRecord' fi # Cas de l’option “-i” if [[ $recid -gt 0 ]] then echo " <option>" >> search$$.xml echo " <key>RecordIDs</key>" >> search$$.xml echo " <value>On</value>" >> search$$.xml echo " </option>" >> search$$.xml fi cat << EOT >> retrieve$$.xml <option> <key>targetNamespace</key> <value>http://scientific.thomsonreuters.com/schema/wok5.4/public/$ns</value> </option> </retrieveParameters> </ns2:retrieve> </soap:Body> </soap:Envelope> EOT curl -X POST -d @retrieve$$.xml -b $cookiejar -c $cookiejar -v 'http://search.webofknowledge.com/esti/wokmws/ws/WokSearch?wsdl' \ -H "Cookie: SID=$sid" 2> $err | xmllint -format - > $out 2>> $err return $? } # fonction verifie function verifie { perl -ne 'if (/<records[^>]*>(.+)/) { $r = $1; $r =~ s|</records>.*||; $r =~ s/</</go; $r =~ s/>/>/go; $r =~ s/&(\w+;)/&$1/go; $r =~ s|</REC>|</REC>\n|go; $r =~ s|<REC |\n<REC |go; print "$r\n"}' $1 | egrep '^<REC ' > tmpWos$$.xml nr=$(cat tmpWos$$.xml | wc -l) (echo "<records>" ; cat tmpWos$$.xml; echo "</records>") | xmllint -format - > /dev/null 2>> $err rc=$? rm -f tmpWos$$.xml if [[ $rc -gt 0 ]] then echo "" echo "Erreur : la réponse de l‘API est incorrecte [code xmllint = $rc]" >&2 echo " $nr / $2 notices déchargées" nettoie exit 4 elif [[ $nr -lt $2 ]] then echo "" echo "Erreur : la réponse de l‘API est incomplète " >&2 echo " $nr / $2 notices déchargées" nettoie exit 4 fi } # Itération max=${taille:-100} delai=${WOS_DELAY:-1} total=$(( $nb - $offset + 1 )) # Vérification de ces variables 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 while [[ $total -gt 0 ]] do if [[ $total -lt $max ]] then max=$total fi SECONDS=0 rc=$(cherche "$offset" "$max") rs=$(perl -e 'print [(stat($ARGV[0]))]->[7]' $out) printf " \r" >&2 if [[ $rc -gt 0 ]] then echo "" echo "Erreur : la réponse de l‘API est incorrecte [code xmllint = $rc]" >&2 echo "" nettoie exit 4 fi if [[ $rs -gt 12000000 ]] then verifie "$out" "$max" fi rc=$(grep -c '<return>' $out 2> /dev/null) if [[ $rc -gt 0 ]] then cat $out >> $sortie else msg=$(perl -ne 'print "$1" if m|<faultstring>(.+?)</faultstring>|;' $out) if [[ -n $msg ]] then echo " " >&2 echo "Erreur : $msg ">&2 echo " " >&2 else echo " " >&2 echo "Erreur indéterminée. " >&2 echo "Voir fichier “$err”. " >&2 echo " " >&2 fi nettoie exit 3 fi total=$(( $total - $max )) offset=$(( $offset + $max )) while [[ $total -gt 0 && $SECONDS -lt $delai ]] do sleep 0.5 done done printf " \r" >&2 nettoie exit 0