Skip to content

Instantly share code, notes, and snippets.

@ThomasG77
Last active April 9, 2024 17:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ThomasG77/339bc4f7964028415d164894b2e5509e to your computer and use it in GitHub Desktop.
Save ThomasG77/339bc4f7964028415d164894b2e5509e to your computer and use it in GitHub Desktop.
Fichiers IGN à disposition via la Géoplateforme

Récupération des URLS de téléchargement de la géoplateforme

On est parti du Service Géoplateforme de téléchargement https://geoservices.ign.fr/services-geoplateforme-telechargement

Les fichiers résultats

Prendre le zip ign_files_list.zip. Il contient

Les filtres listés sur le point d'entrée principal

  • zones_rss_search_geopf.csv
  • formats_rss_search_geopf.csv
  • categories_rss_search_geopf.csv

Les fichiers correspondants au listing des ressources, sous-ressources et fichiers de téléchargement associés avec

  • ressources_search_geopf.csv
  • sub_ressources_search_geopf.csv
  • download__from_sub_ressources_search_geopf_with_stats.csv
  • download__from_sub_ressources_search_geopf_with_stats_no_pva.csv

L'intérêt du download__from_sub_ressources_search_geopf_with_stats.csv est qu'il permet d'anticiper l'espace disque compressé pour le téléchargement et de faire une recherche via un tableur. Attention, il y a 1.8 millions de lignes (avec 1 877 614 lignes sans l'en tête du csv). La majorité sont les PVA (prises de vue aériennes historiques non calées, approximativement placées) qui sont au nombre 1 862 115 lignes) et 15499 lignes pour les autres données. Nous avons de ce fait filtrer les données hors PVA dans un fichier à part download__from_sub_ressources_search_geopf_with_stats_no_pva.csv.

La taille totale des fichiers disponibles sur les serveurs pour les fichiers listés est de 73,44TiB dont 22,98TiB qui ne sont pas des PVA. Il faut aussi noter que le nombre de fichiers réelllement utilisable est inférieur. Nous n'avons pas filtré les fichiers md5 qui permettent de vérifier si un fichier a été corrompu lors du téléchargement.

Aspects techniques

Nous déroulons la recette et des remarques techniques associées ayant permis d'avoir les fichiers ci-dessus

On s'appuie sur curl, yq, jq, xmllint, xq fournit par yq

Récupération des "capabilities"

curl -s https://data.geopf.fr/telechargement/capabilities?pageSize=200 | xmllint --format - >| geopf-download-capabilities.xml

Récupération des filtres possibles

Cela correspond à ceux qui sont mentionnés dans https://geoservices.ign.fr/documentation/services/services-geoplateforme/telechargement#72127

echo '"term","label"' >| zones_rss_search_geopf.csv
xq -c -r --xml-force-list "gpf_dl:zone" '.feed.entry[]."gpf_dl:zone"' geopf-download-capabilities.xml | grep -v '^null' | jq -c -r '.[] | [."@term", ."@label"] | @csv' | grep -v '"",""' | sort | uniq >> zones_rss_search_geopf.csv

echo '"term","label"' >| formats_rss_search_geopf.csv
xq -c -r --xml-force-list "gpf_dl:format" '.feed.entry[]."gpf_dl:format"' geopf-download-capabilities.xml | grep -v '^null' | jq -c -r '.[] | [."@term", ."@label"] | @csv' | grep -v '"",""' | sort | uniq >> formats_rss_search_geopf.csv

echo '"term","label"' >| categories_rss_search_geopf.csv
xq -c -r --xml-force-list "category" '.feed.entry[]."category"' geopf-download-capabilities.xml | grep -v '^null' | jq -c -r '.[] | [."@term", ."@label"] | @csv' | grep -v '"",""' | sort | uniq >> categories_rss_search_geopf.csv

Lister les ressources

Attention, dans la doc, les pages devraient commencer avec le numero 1. Dans les faits, cela commence avec 0. Soit c'est un problème dans l'implémentation soit dans la doc.

curl 'https://data.geopf.fr/telechargement/resource/ADMIN-EXPRESS-COG?pageSize=20&page=1' >| page_1.txt
curl 'https://data.geopf.fr/telechargement/resource/ADMIN-EXPRESS-COG?pageSize=20&page=0' >| page_0.txt
curl 'https://data.geopf.fr/telechargement/resource/ADMIN-EXPRESS-COG?pageSize=20' >| page_default.txt

# Ce qui suit ne retourne rien donc page 0 = page par défaut
diff page_0.txt page_default.txt
diff page_1.txt page_default.txt

Reprenons le listing des ressources

echo '"title","id","link","summary"' >| ressources_search_geopf.csv
xq -c -r '.feed.entry[] | [.title, .id, .link."@href", .summary] | @csv' geopf-download-capabilities.xml >> ressources_search_geopf.csv

Lister les sous-ressources

Boucler sur les ressources pour obtenir les infos associées aux sous-ressources

ressources_url=$(xsv select id ressources_search_geopf.csv | sed '1d')
echo '"sub_res_id","title","id","href","summary","category_term","category_label","zone_term","zone_label","format_term","format_label"' >| sub_ressources_search_geopf.csv
for url in $ressources_url;
  do count_pages=$(curl -s "$url?pageSize=200" | xq -r '.feed | ."@gpf_dl:pagecount"');
     end_seq_pages=$((count_pages - 1));
     for i in $(seq 0 $end_seq_pages);
       do echo "${url}?pageSize=200&page=${i}";
          curl -s "${url}?pageSize=200&page=${i}" | xq -c -r --xml-force-list "entry" '.feed.id as $res_id | .feed.entry[] | [$res_id, if has("title") then .title else "notitle" end , .id, .link."@href", .summary, .category."@term", .category."@label", ."gpf_dl:zone"."@term", ."gpf_dl:zone"."@label", ."gpf_dl:format"."@term", ."gpf_dl:format"."label"] | @csv' >> sub_ressources_search_geopf.csv;
     done;
done;

Ressources non disponibles ci-dessous (ou bien protégée?). Heureusement les dernières dans la liste donc n'a rien planté car je ne teste pas les 404 par défaut...

Il faut aussi noter que pour les gpf_dl:format, on a des cas particuliers où un fichier retourne plusieurs types alors que globalement, il y a un seule type, un shp (nous n'avons pas géré ce cas). A priori, il doit avoir une forme de détection de fichiers compressés pour remplir ce champ.

curl -s https://data.geopf.fr/telechargement/resource/RPG/RPG_2-0__SHP_LAMB93_R93_2021-01-01 | xq .

retourne (partie tronquée)

...
"gpf_dl:format": [
        {
          "@term": "application/octet-stream",
          "@label": "application/octet-stream"
        },
        {
          "@term": "application/x-shapefile",
          "@label": "application/x-shapefile"
        },
        {
          "@term": "image/x-prj",
          "@label": "image/x-prj"
        }
      ]
...

Liste des fichiers associées aux sous-ressources

Pour chacune des sous-ressources, récupérer les fichiers associés

sub_ressources_url=$(xsv select id sub_ressources_search_geopf.csv | sed '1d')
>| download__from_sub_ressources_search_geopf_temp.csv
for url in $sub_ressources_url;
  do count_pages=$(curl -s "$url?pageSize=200" | xq -r '.feed | ."@gpf_dl:pagecount"');
     end_seq_pages=$((count_pages - 1));
     for i in $(seq 0 $end_seq_pages);
       do echo "${url}?pageSize=200&page=${i}";
          curl -s "${url}?pageSize=200&page=${i}" | xq -c -r --xml-force-list "entry" '.feed.id as $res_id | .feed.entry[] | [$res_id, if has("title") then .title else "notitle" end , .id, .link."@href", .summary, .category."@term", .category."@label", ."gpf_dl:zone"."@term", ."gpf_dl:zone"."@label", ."gpf_dl:format"."@term", ."gpf_dl:format"."label"] | @csv' >> download__from_sub_ressources_search_geopf_temp.csv;
     done;
done;

# On nettoye quelques doublons qui posaient problème lors de la jointure ultérieure
echo '"sub_res_id","title","id","href","summary","category_term","category_label","zone_term","zone_label","format_term","format_label"' >| download__from_sub_ressources_search_geopf.csv
sort download__from_sub_ressources_search_geopf_temp.csv | uniq >> download__from_sub_ressources_search_geopf.csv
rm download__from_sub_ressources_search_geopf_temp.csv

Obtention des tailles de fichiers et de leur disponibilité

>| configfile.txt
for i in $(xsv select href <(cat download__from_sub_ressources_search_geopf.csv) | sed '1d');
  do echo 'url = "'$i'"' >> configfile.txt;
done;

echo "url,content_length,response_code" >| files_stats.txt
curl -L --head --parallel --parallel-immediate --parallel-max 4 --write-out '%output{>>files_stats.txt}%{url},%header{content-length},%{response_code}\n' --config configfile.txt > /dev/null

On a eu quelques erreurs 503, qu'on a géré en appliquant le flag -L de redirection de "curl".

On a identifié une erreur 404 sur https://data.geopf.fr/telechargement/download/pva/92PHQ9651/263562_IGNF_PVA_1-0__1954-06-08__C92PHQ9651_1954_NOUVELLE-CALEDONIE14_19X22_0127.tif.aux.xml

Aperçu de la taille disques des fichiers total

xsv search -s response_code 200 files_stats.txt | xsv select content_length | sed '1d' | paste -s -d+ - | bc | numfmt --to=iec-i --suffix=B --format="%9.2f"
# 73,44TiB

Jointure pour avoir les fichiers de téléchargement associées à leur taille

xsv join --no-case id download__from_sub_ressources_search_geopf.csv url files_stats.txt | xsv select 'sub_res_id,title,id,summary,category_term,category_label,zone_term,zone_label,content_length,response_code' >| download__from_sub_ressources_search_geopf_with_stats.csv
grep -v '/pva/' download__from_sub_ressources_search_geopf_with_stats.csv >| download__from_sub_ressources_search_geopf_with_stats_no_pva.csv

Taille hors PVA

xsv search -s response_code 200 download__from_sub_ressources_search_geopf_with_stats_no_pva.csv | xsv select content_length | sed '1d' | paste -s -d+ - | bc | numfmt --to=iec-i --suffix=B --format="%9.2f"
# 22,98TiB

On zippe tout

zip ign_files_list.zip categories_rss_search_geopf.csv download__from_sub_ressources_search_geopf_with_stats.csv download__from_sub_ressources_search_geopf_with_stats_no_pva.csv formats_rss_search_geopf.csv ressources_search_geopf.csv sub_ressources_search_geopf.csv zones_rss_search_geopf.csv

Retour fonctionnel à date

Un truc très ennuyeux du point de vue fonctionnel pour moi: il n'y a pas de date "Last-Modified" du type "Fri, 05 Apr 2024 15:58:59 GMT" dans les flux. Les noms de fichiers sont daté mais cela reste nettement moins pratique. L'intérêt de cette fonctionnalité c'est de permettre la reprise des téléchargements et savoir si fichier changé (exemple d'un fichier réuploadé suite à des corrections). Cela semble être caché par l'outil Kong (déduit des en-têtes http) utilisé en front des services de l'IGN.

J'aimerais aussi avoir des dates pour pouvoir filtrer par date. C'est à priori prévu via les filtres (mentionné dans la documentation) mais ce n'est pas encore disponible.

This file has been truncated, but you can view the full file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment