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 utilisationModifier

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 pagesModifier

  • 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 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) ;
  • 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

Il est également possible de passer 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 margesModifier

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

CodeModifier

# 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)
    with urllib.request.urlopen(url) as f:
        return json.loads(f.read())
        
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 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)
        with urllib.request.urlopen(url) as f:
            if verbose:
                print("Enregistrement dans {}.".format(outfic))
            with open(outfic, "wb") as fic:
                fic.write(f.read())

main()

Considérations techniquesModifier

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 aussiModifier

  • 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.