Compare commits

..

11 Commits

3 changed files with 80 additions and 68 deletions

View File

@ -2,6 +2,12 @@
Récupération de Données OSM via Overpass Récupération de Données OSM via Overpass
## Prérequis
`pip3 install requests`
`pip3 install pyexcel-ods3`
## But ## But
Ce script sert à récupérer (en JSON et tableau ods) les infos de stationnement vélo, d'ateliers, d'associations, vendeurs, réparateurs et fabricants de vélo. Ce script sert à récupérer (en JSON et tableau ods) les infos de stationnement vélo, d'ateliers, d'associations, vendeurs, réparateurs et fabricants de vélo.
@ -39,6 +45,11 @@ Ces chemins sont relatifs à `rdoo.py`, il est possible de passer des chemins ab
Il est possible de ne pas archiver en passant l'argument `-na, --no-archive`. Il est possible de ne pas archiver en passant l'argument `-na, --no-archive`.
## Umap
Les fichiers json générés peuvent être directements utilisés dans [umap](https://umap.openstreetmap.fr/fr/) en les [important](https://wiki.openstreetmap.org/wiki/FR:UMap/Guide/Importer_un_fichier_de_donn%C3%A9es) et choisissant le format de données `osm`.
Si vous disposez d'un serveur pour héberger le script ou ses résultats, le lien du fichier peut être utilisé directement dans umap comme `données distantes` d'un calque, en cochant `dynamique` et `avec proxy`.
## Inspirations / ressources : ## Inspirations / ressources :
### urls ressources ### urls ressources
- https://towardsdatascience.com/loading-data-from-openstreetmap-with-python-and-the-overpass-api-513882a27fd0 - https://towardsdatascience.com/loading-data-from-openstreetmap-with-python-and-the-overpass-api-513882a27fd0
@ -55,7 +66,6 @@ penser à cocher "proxy" dans la rubrique "données distantes" du calque
### export ODS : ### export ODS :
- https://pythonhosted.org/pyexcel-ods/ - https://pythonhosted.org/pyexcel-ods/
`pip3 install pyexcel-ods3`
## Licence ## Licence

View File

@ -25,6 +25,7 @@ import os
import datetime import datetime
import shutil import shutil
import pathlib import pathlib
import csv
from collections import OrderedDict from collections import OrderedDict
import requests import requests
from pyexcel_ods3 import save_data from pyexcel_ods3 import save_data
@ -148,77 +149,74 @@ class Utils:
return response.json() return response.json()
def run_reverse_geocoding(self, lat, lon): def geocodage_csv(self, data):
"""Retourne une adresse JSON à partir d'une position GPS.""" """
Renseigne une adresse pour chaque élément de data
en une fois via csv
"""
url = self.geo_api_url + "/reverse/" url = self.geo_api_url + "/reverse/csv/"
response = requests.get(url, params={"lon": str(lon), "lat": str(lat)}) # création du fichier à envoyer à l'API
with open("tmp_geocodage.csv", "w", newline="") as tmp_csv_file:
csv_writer = csv.writer(tmp_csv_file)
csv_writer.writerow(["lat", "lon"])
for element in data["elements"]:
if element["type"] == "node":
csv_writer.writerow([element["lat"], element["lon"]])
else:
csv_writer.writerow(
[element["center"]["lat"], element["center"]["lon"]]
)
# préparation et envoi de la requête
payload = dict(
[("data", ("tmp_geocodage.csv", open("tmp_geocodage.csv", "rb").read()))]
)
response = requests.post(url, files=payload)
# nettoyage
os.remove("tmp_geocodage.csv")
if response.status_code != 200: if response.status_code != 200:
raise errors.GeoApiError(response.status_code) raise errors.GeoApiError(response.status_code)
return response.json() # affectation des addresses
def geocodage(self, data):
"""Renseigne une adresse pour chaque élément de data"""
for element in data["elements"]: for element in data["elements"]:
for row in csv.DictReader(response.text.splitlines()):
if element["type"] == "node": if element["type"] == "node":
rev_geocode = self.run_reverse_geocoding(element["lat"], element["lon"]) lat_ok = row["lat"] == str(element["lat"])
lon_ok = row["lon"] == str(element["lon"])
else: else:
rev_geocode = self.run_reverse_geocoding( lat_ok = row["lat"] == str(element["center"]["lat"])
element["center"]["lat"], element["center"]["lon"] lon_ok = row["lon"] == str(element["center"]["lon"])
)
api_adresse = rev_geocode["features"][0] if lat_ok and lon_ok:
element["tags"]["api_adresse:geometry:coordinates:lon"] = row[
element["tags"]["api_adresse:geometry:coordinates:lon"] = api_adresse[ "result_longitude"
"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"][ element["tags"]["api_adresse:geometry:coordinates:lat"] = row[
"score" "result_latitude"
] ]
element["tags"]["api_adresse:properties:label"] = row[
if "housenumber" in api_adresse["properties"]: "result_label"
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:housenumber"] = row[
element["tags"]["api_adresse:properties:name"] = api_adresse["properties"][ "result_housenumber"
"name"
] ]
element["tags"]["api_adresse:properties:postcode"] = api_adresse[ element["tags"]["api_adresse:properties:type"] = row["result_type"]
"properties" element["tags"]["api_adresse:properties:name"] = row["result_name"]
]["postcode"] element["tags"]["api_adresse:properties:postcode"] = row[
element["tags"]["api_adresse:properties:citycode"] = api_adresse[ "result_postcode"
"properties"
]["citycode"]
element["tags"]["api_adresse:properties:city"] = api_adresse["properties"][
"city"
] ]
element["tags"]["api_adresse:properties:citycode"] = row[
if "street" in api_adresse["properties"]: "result_citycode"
element["tags"]["api_adresse:properties:street"] = api_adresse[ ]
"properties" element["tags"]["api_adresse:properties:city"] = row["result_city"]
]["street"] element["tags"]["api_adresse:properties:street"] = row[
"result_street"
element["tags"]["api_adresse:properties:attribution"] = rev_geocode[
"attribution"
] ]
element["tags"]["api_adresse:properties:licence"] = rev_geocode["licence"]
logging.info("Géocodage inversé terminé") logging.info("Géocodage inversé terminé")
@ -242,7 +240,11 @@ class Utils:
return return
date_fichier = datetime.date.fromtimestamp(fichier.stat().st_ctime) date_fichier = datetime.date.fromtimestamp(fichier.stat().st_ctime)
os.makedirs(dossier_archive + str(date_fichier), exist_ok=True)
# une seule archive par date
if os.path.isdir(dossier_archive + str(date_fichier)):
shutil.rmtree(dossier_archive + str(date_fichier))
os.makedirs(dossier_archive + str(date_fichier))
# pylint: disable=W0106 # pylint: disable=W0106
[ [

View File

@ -169,7 +169,7 @@ def main():
if nb_resultats > 0: if nb_resultats > 0:
if args.geocoding_inverse: if args.geocoding_inverse:
# géocodage inverse # géocodage inverse
data = utils.geocodage(data) data = utils.geocodage_csv(data)
# traduction # traduction
data = utils.traduction( data = utils.traduction(
@ -188,7 +188,7 @@ def main():
break break
except errors.ApiError: except errors.ApiError:
if nb_essai == MAX_RETRY: if nb_essai >= MAX_RETRY - 1:
logging.error("Trop d'erreurs d'API - abandon") logging.error("Trop d'erreurs d'API - abandon")
exit() exit()