#!/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