Autres exemples d'APIs
Ce chapitre est une parenthèse dans ce tutoriel, pour présenter quelques exemples d'exploitation d'APIs.
Un XML (http://mob.u-strasbg.fr/)
L'université de Strasbourg entretient une API fournissant des POIs, exemple :
La forme du XML généré est plus classique que ceux d'OSM :
<rss version="2.0"> <poi> <id>1</id> <name>Central</name> <latitude>48.5803337</latitude> <longitude>7.7655637</longitude> <floor/> <type>campus</type> <description/> <url>http://fr.wikipedia.org/wiki/Campus_central_de_Strasbourg</url> <url_image/> <tags/> <capacity>0</capacity> </poi> <poi> <id>2</id> ...
Pour extraire les données de ce type d'XML :
(Attention au &)
import requests import xml.etree.ElementTree r = requests.get('http://mob.u-strasbg.fr/cgi-bin/odudsApi.py?method=search&id=allpois') root = xml.etree.ElementTree.fromstring(r.content) for my_poi in root.findall('poi'): my_name = my_poi.find('name').text print(my_name)
Afficher les points à partir de leurs coordonnées
Vous pouvez vous entraîner avec le code simplifié de cet article, chapitre Temporary layer.
Le code suivant, dans un projet QGIS vide, affiche un fond de carte OSM, crée puis affiche une couche virtuelle de points, avec 2 champs, peuplée des points issus d'un XML. Toujours à partir de l'API de l'université de Strasbourg :
(Attention au &)
import requests import xml.etree.ElementTree from qgis.PyQt.QtCore import QVariant project = QgsProject.instance() project.removeAllMapLayers() iface.mapCanvas().refresh() crs = QgsCoordinateReferenceSystem.fromEpsgId(4326) project.setCrs(crs) project.setEllipsoid('EPSG:4326') urlWithParams = "type=xyz&url=http://tile.openstreetmap.org/{z}/{x}/{y}.png" osm = QgsRasterLayer(urlWithParams, "OpenStreetMap", "wms") # point_vector point_vector = QgsVectorLayer("Point", "my_points", "memory") project.addMapLayer(osm) project.addMapLayer(point_vector) root = project.layerTreeRoot() root.setHasCustomLayerOrder (True) order = root.customLayerOrder() order.insert(0, order.pop(order.index(point_vector))) order.insert(1, order.pop(order.index(osm))) root.setCustomLayerOrder(order) pr = point_vector.dataProvider() pr.addAttributes([QgsField("id", QVariant.Int), QgsField("name", QVariant.String)]) point_vector.updateFields() r = requests.get('http://mob.u-strasbg.fr/cgi-bin/odudsApi.py?method=search&id=allpois') root = xml.etree.ElementTree.fromstring(r.content) for my_poi in root.findall('poi'): my_id = int(my_poi.find('id').text) my_name = str(my_poi.find('name').text) my_longitude = float(my_poi.find('longitude').text) my_latitude = float(my_poi.find('latitude').text) #print(my_id, my_name, my_longitude, my_latitude) f = QgsFeature() f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(my_longitude, my_latitude))) f.setAttributes([my_id, my_name]) pr.addFeature(f) point_vector.updateExtents() project.addMapLayer(point_vector) iface.mapCanvas().refresh()
Aller chercher l'image sous condition
Dans la boucle, ajoutez :
my_image = str(my_poi.find('url_image').text) if my_image == "None": my_image = "" elif my_image != "None": my_image = "https://mob.u-strasbg.fr/geoloc/url_image/" + my_image print(my_image)
Un JSON simple (data.culture.gouv.fr, monuments historiques)
Le site data.culture.gouv.fr propose plusieurs APIs, dont les données sont fournis en JSON.
Exemple avec la liste des immeubles parisiens protégés au titre des monuments historiques :
Quand vous êtes confronté à ce type de fichiers, dont la visualisation en ligne n'est pas toujours aisée, il existe ce type d'outil en ligne qui vous permettra d'en comprendre la structure ou de tester votre fichier :
Sur jsonviewer utilisez le bouton Load JSON data et copiez-y l'URL (supprimez le « s » du https de votre URL si besoin). Ou alors vous pouvez coller l'intégralité du contenu du fichier dans l'onglet Text et cliquer sur Format.
Sur geojson.io copiez vos données GEOJSON dans l'encart prévu, ou ajoutez l'adresse de votre fichier GEOJSON comme dans l'exemple ci-dessus (à la place de [URL]).
Pour parser ce type de JSON, et en extraire les données :
(Attention au &)
import json import requests response = requests.get("https://data.culture.gouv.fr/api/records/1.0/search/?dataset=liste-des-immeubles-proteges-au-titre-des-monuments-historiques&q=&facet=reg&facet=dpt_lettre&refine.dpt_lettre=Paris") my_file = json.loads(response.text) my_json = my_file["records"] for my_block in my_json: my_fields = my_block["fields"] print(str(my_fields["adresse_forme_editoriale"]).replace("'", ''))
Les lignes 4 et 5 en font un JSON lisible pour Python.
Les données qui nous intéressent sont dans le bloc records
, nous l'isolons donc avec la ligne 7.
La ligne 9 boucle sur le bloc records
, et pour chaque sous-blocs fields
affiche les données du tag adresse_forme_editoriale
.
Les autres APIs de data.culture.gouv.fr
Si vous allez sur l'onglet Les données, et que vous cliquez sur presque n'importe quelle API, vous verrez que leur organisation est à peu près similaire.
Exemple avec l'API Répertoire des Musées de France : base Muséofile, son onglet API permet de modifier les paramètres de l'API. L'URL par défaut (en bas du formulaire) est la suivante :
- Les affichages sont bridés à un maximum de 100 enregistrements.
- On contrôle le nombre d'enregistrements affichés avec le paramètre
limit
. - On a un paramètre
total_count
pour connaître le nombre d'enregistrements. - D'autres champs sont filtrables avec le paramètre
where
.
On peut donc construire des URLs et itérer à travers les pages JSON des APIs pour récupérer les bases de données dynamiquement.
Autre exemples d'URLs :
https://data.culture.gouv.fr/api/explore/v2.1/catalog/datasets/musees-de-france-base-museofile/records?limit=20&offset=20
Une autre solution est de lancer le téléchargement du CSV complet à chaque fois que nécessaire, puis l'utiliser, mais c'est moins souple et plus lourd.
Un GEOJSON
Pour ouvrir un fichier GEOJSON, ce ne sera pas compliqué (source : webgeodatavore) :
iface.addVectorLayer('https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_50m_populated_places.geojson', 'Populated places', 'ogr')
Mais pour ouvrir des données GEOJSON brutes (construites à la volée par une API par exemple, ou simplement non-accessibles par URL), alors vous devrez d'abord les enregistrer dans un fichier, puis ouvir ce fichier. Vous pouvez vous inspirer du chapitre nommé Zones isochrones de cet article, qui utilise l'API openrouteservice.org pour créer des GeoJson de zones isochrones.