Wikisource:Gallica/gallica.py

Ce script permet de télécharger une partie ou l’ensemble des pages d'un document de Gallica en haute résolution, c’est-à-dire avec une qualité meilleure que celle du document PDF qu’on obtient en téléchargeant un document sur le site Gallica.

Il permet également, de manière optionnelle, de rogner les pages en supprimant les marges.

Pré-requis et utilisation modifier

Le script a été développé sous Windows et utilisé sous Linux Mint.

Le seul pré-requis est en principe Python 3.

Utilisation de base : téléchargement d’un ensemble de pages modifier

  • S'il n’est pas déjà présent sur votre système, télécharger et installer Python 3. Le script ne fonctionne pas sous Python 2 (mais serait facile à adapter si vous connaissez Python).
  • Copier le code présent dans la section « Code » et le coller dans un fichier intitulé « gallica.py ». Attention : Python est très sensible à l’indentation des lignes, qui ne doit pas être modifiée. En outre, il peut être nécessaire de vérifier que le fichier est enregistré avec l’encodage UTF-8 (en cas de problème, essayer de supprimer tous les caractères accentués dans le script).
  • Exécuter le script avec Python. On suppose dans la suite que Python 3 peut être exécuté avec la commande « python », mais cela peut varier selon le système.

Trois paramètres doivent être fournis au minimum :

  • le numéro ARK (qui figure dans l'URL du document sur Gallica). Par souci de simplicité, vous pouvez fournir l’URL complète du document sur Gallica, et le script détectera lui-même le numéro ARK ;
  • la page de début (numérotation à partir de 1, comme dans le document PDF) ;
  • la page de fin.

Par exemple pour récupérer les pages 11 à 638 du songe de Poliphile, ouvrage doté de nombreuses illustrations qui méritent un téléchargement en haute résolution :

   python gallica.py bpt6k1073366t 11 638

Ou en passant l’adresse complète du document (ou même de l’une de ses pages) par copier/coller depuis le champ « URL » sur le site de Gallica :

  python gallica.py https://gallica.bnf.fr/ark:/12148/bpt6k1073366t 11 638

Utilisation avancée : suppression des marges modifier

Si toutes les pages ont une taille et des marges comparables, on peut supprimer ces marges en utilisant les paramètres optionnels. Dans l’exemple précédent, les pages font près de 2000 pixels de largeur et 3500 pixels de hauteur avec des marges hautes et basses généreuses. On supprime donc 100 pixels à gauche et à droite, 400 pixels en haut et 600 en bas :

   python gallica.py bpt6k1073366t 11 638 -x 100 --largeur 1800 -y 400 --hauteur 2500
# Télécharge de Gallica un livre en haute définition
# À enregistrer sous le nom gallica.py et exécuter avec Python 3. 
# Exemple pour récupérer les pages 1 à 50
# du document https://gallica.bnf.fr/ark:/12148/bpt6k1073366t/ :
#     python gallica.py bpt6k1073366t 1 50

import argparse
import urllib.request
import json
import re
import sys

def get_size(ark, i):
    url = "https://gallica.bnf.fr/iiif/ark:/12148/{}/f{}/info.json".format(ark, i)
    try:
        with urllib.request.urlopen(url) as f:
            return json.loads(f.read())
    except urllib.error.HTTPError as exc:
        print("Erreur {} en récupérant {}".format(exc, url))
        return None
        
def main():
    verbose = False
    
    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawDescriptionHelpFormatter,
        description="""
Récupère un ouvrage de Gallica en haute résolution.
Trois arguments doivent être passés : le numéro ARK (ou l'URL complète 
du document sur Gallica), la page de début et la page de fin. 
Exemple :
   python gallica.py bpt6k1073366t 1 649
   python gallica.py https://gallica.bnf.fr/ark:/12148/bpt6k1073366t 1 649

Si toutes les pages ont une taille et des marges comparables,
on peut supprimer ces marges en utilisant les paramètres optionnels :
   python gallica.py bpt6k1073366t 1 649 -x 100 --largeur 1800 -y 400 --hauteur 2500
""")
    # Arguments obligatoires
    parser.add_argument('ark', help="URL complète d'un ouvrage sur Gallica, ou bien identifiant ARK")
    parser.add_argument('debut', type=int, help="numéro de la première page à récupérer")
    parser.add_argument('fin', type=int, help="numéro de la dernièer page à récupérer")
    # Arguments optionnels
    parser.add_argument('-x', type=int, default=0, help="force l'abscisse de départ")
    parser.add_argument('-y', type=int, default=0, help="force l'ordonnée de départ")
    parser.add_argument('-L', '--largeur', type=int, help="force la largeur")
    parser.add_argument('-H', '--hauteur', type=int, help="force la hauteur")
    parser.add_argument('-v', '--verbose', action="store_true")
    args = parser.parse_args()

    if args.debut is None or args.fin is None or args.ark is None:
        parser.print_usage()
        sys.exit(2)
    
    if args.verbose:
        verbose = True
        
    for i in range(args.debut, args.fin + 1):
        (ark, debut, fin, x, y, largeur, hauteur) = (
            args.ark, args.debut, args.fin, args.x, args.y, args.largeur, args.hauteur,
        )
        m = re.match(r'https://gallica.bnf.fr/ark:/[^/]+/(?P<ark>[^/]+).*', ark)
        if m:
            ark = m.group("ark")
            print("ARK détecté : {}".format(ark))
        if largeur is None or hauteur is None:
            taille = get_size(ark, i)
            if taille is None:
                print("Opération interrompue")
                return
            if verbose:
                print("Taille de la page : {}/{}".format(taille["width"], taille["height"]))
            if largeur is None:
                largeur = taille["width"]
            if hauteur is None:
                hauteur = taille["height"]
        if verbose:
            print("Rectangle : x={}, y={}, largeur={}, hauteur={}".format(
                x, y, largeur, hauteur,
            ))
        url = "https://gallica.bnf.fr/iiif/ark:/12148/{}/f{}/{},{},{},{}/full/0/native.jpg".format(
        ark, i, x, y, largeur, hauteur,
        )
        print("Page {}...".format(i))
        if verbose:
            print("Récupération de {}...".format(url))
        outfic = "{}_{:04}.jpg".format(ark, i)
        try:
            with urllib.request.urlopen(url) as f:
                if verbose:
                    print("Enregistrement dans {}.".format(outfic))
                with open(outfic, "wb") as fic:
                    fic.write(f.read())
        except urllib.error.HTTPError as exc:
            print("Erreur {} en récupérant {}".format(exc, url))
            return

main()

Considérations techniques modifier

Si ce script ne fonctionne pas, les raisons suivantes peuvent être envisagées :

  • un bug dans le script, bien sûr, ou une mauvaise installation (problème d’indentation du code, en particulier) ;
  • un problème d'accès SSL : dans ce cas, essayer de remplacer « https » par « http » partout dans le code ;
  • un dysfonctionnement ou un changement de comportement de l’interface IIIF de Gallica, qui est connue et documentée.

Voir aussi modifier

  • Pour toute question sur ce script :
    • invoquer le script avec le paramètre « -h » pour avoir des informations sur chaque paramètre ;
    • laisser un message sur Discussion Utilisateur:Seudo.
  • D'autres méthodes pour récupérer des pages de Gallica sont présentes sur : Wikisource:Gallica.