Newer
Older
api-wos / SOAP / WosRetrieve.sh
@besagni besagni on 25 Jul 2022 9 KB Homogénéisation des options
#!/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/&lt;/</go; 
                $r =~ s/&gt;/>/go; 
                $r =~ s/&amp;(\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