outils_OSM/recup_donnees_osm_overpass.py

177 lines
5.9 KiB
Python
Raw Normal View History

2021-09-26 12:52:37 +02:00
#!/usr/bin/env python3
2021-10-10 16:50:27 +02:00
"""
Module principal : 
- récupération de données par appel à Overpass
- géocodage inverse
- export des données en JSON pour utilisation avec umap
- sauvegarde des données en ods
"""
2021-09-26 12:52:37 +02:00
# inspiration :
# https://towardsdatascience.com/loading-data-from-openstreetmap-with-python-and-the-overpass-api-513882a27fd0
# https://geo.api.gouv.fr/adresse
# https://wiki.cartocite.fr/doku.php?id=umap:10_-_je_valorise_les_donnees_openstreetmap_avec_umap
# https://sites-formations.univ-rennes2.fr/mastersigat/Cours/Intro_Overpass.pdf
# usage des tags : https://taginfo.openstreetmap.org/tags/?key=amenity&value=bicycle_parking#combinations
# exemple URL données pour umap : https://www.velocite63.fr/velocite63/OSM/stationnements_velos_publics.json
# penser à cocher "proxy" dans la rubrique "données distantes" du calque
# export ODS :
# https://pythonhosted.org/pyexcel-ods/
# pip3 install pyexcel-ods3
import time
import os
from osm_vc63 import errors
from osm_vc63 import requetes
from osm_vc63.utils import Utils
2021-09-26 12:52:37 +02:00
2021-10-10 16:50:27 +02:00
OVERPASS_URL = "http://overpass-api.de/api/interpreter"
GEO_API_URL = "https://api-adresse.data.gouv.fr"
DOSSIER_SAUVEGARDE = "resultats/"
2021-09-26 12:52:37 +02:00
# nombre maxi de retries quand echec API
2021-10-10 16:50:27 +02:00
MAX_RETRY = 4
2021-09-26 12:52:37 +02:00
# delai en secondes entre les tentatives
2021-10-10 16:50:27 +02:00
RETRY_DELAY = 120
2021-09-26 12:52:37 +02:00
# id du département "Puy de Dôme" : 7406
# id Riom : 1693144
# id Clermont : 110866
# id Romagnat : 138269
# l'id de l'area se calcule en ajoutant 3600000000 au numéro de l'objet OSM
2021-10-10 16:50:27 +02:00
AIRE_DE_RECHERCHE = str(3600000000 + 110866)
2021-09-26 12:52:37 +02:00
# ----------------------------------------------
trad_bicycle_parking = {
"stands": "Arceaux",
"wall_loops": "Pince roues",
"rack": "Râteliers",
"anchors": "Ancrage",
"shed": "Abri collectif",
"bollard": "Potelet",
"lockers": "Abris individuels",
"wide_stands": "Arceaux espacés",
"ground_slots": "Fente dans le sol",
"building": "Bâtiment",
"informal": "Informel",
"wave": "Râteliers",
"streetpod": "Arceaux",
"tree": "Arbre à bicyclettes",
"crossbar": "Barre",
"rope": "Câble",
"two-tier": "Deux étages",
"floor": "Sol",
2021-10-10 10:56:13 +02:00
"handlebar_holder": "Accroche-guidons",
}
2021-10-09 15:10:36 +02:00
2021-09-26 12:52:37 +02:00
2021-10-10 10:56:13 +02:00
def executer_requete_et_exporter_resultats(
nom_req, critere, aire_de_recherche, overpass_query_fields
):
2021-10-10 16:50:27 +02:00
"""
Appelle Overpass et exporte les résultats
nom_req : nom de la requête (type d'informations recherchées)
critere : requête passée à Overpass
aire_de_recherche : zone géographique d'intérêt
overpass_query_fields : champs récupérés pour la réponse
"""
2021-09-26 12:52:37 +02:00
2021-10-10 16:50:27 +02:00
utils = Utils(OVERPASS_URL, GEO_API_URL, DOSSIER_SAUVEGARDE)
data = utils.run_overpass_query(critere, aire_de_recherche)
2021-09-26 12:52:37 +02:00
nb_elements = len(data["elements"])
2021-10-10 10:56:13 +02:00
print("Nombre d'elements : " + str(nb_elements))
"""
2021-09-26 12:52:37 +02:00
print("Géocodage inversé : ", end="", flush=True)
# @TODO : optimiser en faisant un appel au service /reverse/csv/ plutot que le service unitaire /reverse/
for element in data["elements"]:
if (element["type"] == "node") :
rev_geocode = run_reverse_geocoding(element["lat"], element["lon"])
else :
rev_geocode = run_reverse_geocoding(element["center"]["lat"], element["center"]["lon"])
api_adresse = rev_geocode["features"][0]
element["tags"]["api_adresse:geometry:coordinates:lon"] = api_adresse["geometry"]["coordinates"][0]
element["tags"]["api_adresse:geometry:coordinates:lat"] = api_adresse["geometry"]["coordinates"][1]
element["tags"]["api_adresse:properties:label"] = api_adresse["properties"]["label"]
element["tags"]["api_adresse:properties:score"] = api_adresse["properties"]["score"]
if ("housenumber" in api_adresse["properties"]) :
element["tags"]["api_adresse:properties:housenumber"] = api_adresse["properties"]["housenumber"]
element["tags"]["api_adresse:properties:type"] = api_adresse["properties"]["type"]
element["tags"]["api_adresse:properties:name"] = api_adresse["properties"]["name"]
element["tags"]["api_adresse:properties:postcode"] = api_adresse["properties"]["postcode"]
element["tags"]["api_adresse:properties:citycode"] = api_adresse["properties"]["citycode"]
element["tags"]["api_adresse:properties:city"] = api_adresse["properties"]["city"]
if ("street" in api_adresse["properties"]) :
element["tags"]["api_adresse:properties:street"] = api_adresse["properties"]["street"]
element["tags"]["api_adresse:properties:attribution"] = rev_geocode["attribution"]
element["tags"]["api_adresse:properties:licence"] = rev_geocode["licence"]
# traduction
if "bicycle_parking" in element["tags"]:
element["tags"]["bicycle_parking"] = trad_bicycle_parking[element["tags"]["bicycle_parking"]]
print("X", end="", flush=True)
#else :
# print("-", end="", flush=True)
print()
"""
2021-09-26 12:52:37 +02:00
export_json = utils.nettoyage_json_pour_umap(data, overpass_query_fields)
2021-09-26 12:52:37 +02:00
2021-10-09 15:10:36 +02:00
# Sauvegarde
2021-10-10 16:50:27 +02:00
os.makedirs(DOSSIER_SAUVEGARDE, exist_ok=True)
2021-09-26 12:52:37 +02:00
2021-10-10 16:32:16 +02:00
utils.save_as_json(export_json, nom_req)
utils.save_as_ods(overpass_query_fields, data, nom_req)
2021-09-26 12:52:37 +02:00
2021-10-09 14:31:01 +02:00
def main():
2021-10-10 16:50:27 +02:00
"""Routine principale"""
2021-09-26 12:52:37 +02:00
2021-10-10 16:53:12 +02:00
for req in requetes.REQS:
2021-10-10 16:50:27 +02:00
for nb_essai in range(MAX_RETRY): # on tente max_retry fois
2021-10-09 14:31:01 +02:00
try:
executer_requete_et_exporter_resultats(
2021-10-10 16:50:27 +02:00
req.nom, req.critere, AIRE_DE_RECHERCHE, req.champs
2021-10-09 14:31:01 +02:00
)
break
2021-10-10 16:31:54 +02:00
except errors.ApiError:
2021-10-10 10:56:13 +02:00
2021-10-10 16:50:27 +02:00
if nb_essai == MAX_RETRY:
2021-10-09 14:31:01 +02:00
print("trop d'erreurs d'API - abandon")
2021-09-26 12:52:37 +02:00
exit()
2021-10-10 10:56:13 +02:00
2021-10-10 16:50:27 +02:00
print("erreur API - on retente dans " + str(RETRY_DELAY) + "s")
2021-10-10 10:56:13 +02:00
2021-10-10 16:50:27 +02:00
time.sleep(RETRY_DELAY)
2021-10-10 10:56:13 +02:00
2021-10-09 14:31:01 +02:00
print("Fini")
2021-09-26 12:52:37 +02:00
2021-10-09 14:31:01 +02:00
if __name__ == "__main__":
main()