Autres exemples d'APIs
Ce chapitre est une parenthèse dans ce tutoriel, pour présenter quelques exemples d'exploitation d'APIs.
Un XML classique
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 :
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)
Un JSON
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). 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 :
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(my_fields["wadrs"])
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 wadrs
.
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.
Exemple avec l'excellente API de zones isochrones d'openrouteservice (votre obtiendrez une clé gratuite après une rapide inscription) :
import requests body = {"locations":[[8.681495,49.41461],[8.686507,49.41943]],"range":[300,200]} headers = { 'Accept': 'application/json, application/geo+json, application/gpx+xml, img/png; charset=utf-8', 'Authorization': 'VOTRE CLE API', 'Content-Type': 'application/geo+json; charset=utf-8' } call = requests.post('https://api.openrouteservice.org/v2/isochrones/driving-car', json=body, headers=headers) #print(call.status_code, call.reason) #print(call.text) with open('C:/Users/Georges/Downloads/myfile.geoson', 'w', encoding='utf-8') as outfile: outfile.write(call.text) iface.addVectorLayer('C:/Users/Georges/Downloads/myfile.geoson', 'Isochrones', 'ogr')
Afficher des points à partir de leurs coordonnées issues d'une API
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 :
import requests import xml.etree.ElementTree # VIDER PROJET QgsProject.instance().removeAllMapLayers() iface.mapCanvas().refresh() # PARAMETRES OSM urlWithParams = "type=xyz&url=http://tile.openstreetmap.org/{z}/{x}/{y}.png" osm = QgsRasterLayer(urlWithParams, "OpenStreetMap", "wms") # CREER UNE COUCHE VIRTUELLE DE POINTS point_vector = QgsVectorLayer("Point", "my_points", "memory") # AFFICHER LES COUCHES QgsProject.instance().addMapLayer(osm) QgsProject.instance().addMapLayer(point_vector) # AJOUTER CHAMPS DANS point_vector from qgis.PyQt.QtCore import QVariant pr = point_vector.dataProvider() pr.addAttributes([QgsField("id", QVariant.Int), QgsField("name", QVariant.String)]) point_vector.updateFields() # PARSER LE FICHIER 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) # EDITER COUCHE VIRTUELLE f = QgsFeature() f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(my_longitude, my_latitude))) f.setAttributes([my_id, my_name]) pr.addFeature(f) point_vector.updateExtents() QgsProject.instance().addMapLayer(point_vector) # RAFRAICHIR iface.mapCanvas().refresh() # CRS my_crs=QgsCoordinateReferenceSystem(3857) QgsProject.instance().setCrs(my_crs)