Files
osmsearch/osmsearch.py
fordprefect 0b7184185f TODO added
2020-03-26 19:16:36 +01:00

104 lines
3.2 KiB
Python

#!/usr/bin/python
"""
Script to retrieve all Openstreetmap items matching a query and save
them as GPX Waypoints to a given output file in GPX format.
"""
__author__ = "fordprefect"
__date__ = "2020-03-26"
__version__ = "0.1"
import gpxpy
import requests
import os
import sys
assert sys.version_info >= (3, 6), "At least Python 3.8 required due to fStrings. Replace all f\"\" and comment this line to enable running in lower versions (but really, you should just update your Python version…)."
class OSMSearch():
def __init__(self, args):
self.url = args.pop("url")
self.maxsearchnums = args.pop("maxsearchnums")
self.gpxfilename = args.pop("outputfilename")
self.use_boundingbox = args.pop("use_boundingbox")
self.ignore_ids = args.pop("ignore_ids")
if self.use_boundingbox:
assert isinstance(list, args["boundingbox"])
assert len(args["boundingbox"]) == 4
else:
args.pop("boundingbox")
self.searchargs = args
self.initialize_gpx_file()
self.search()
self.save_to_disk()
def initialize_gpx_file(self):
if os.path.isfile(self.gpxfilename):
raise NotImplementedError("We don't know how to deal with existing files yet, sry")
# TODO: file name collision? either:
# 1) amend file
#self.gpxfile = gpxpy.parse(open(gpxfilename, "r"))
# 2) refuse to work
# 3) alter file name
else:
self.gpxfile = gpxpy.gpx.GPX()
def get_argstring(self):
argstrings = []
if self.use_boundingbox:
argstring.append(",".join(list(map(str, self.searchargs["boundingbox"]))))
if self.ignore_ids != []:
argstrings.append(f"ignore_ids=" + ",".join(list(map(str, self.ignore_ids))))
for arg in self.searchargs:
argstrings.append(f"{arg}={self.searchargs[arg]}")
return "?"+"&".join(argstrings)
def search(self):
"""
"""
for i in range(self.maxsearchnums):
# fetch request
r = requests.get(self.url + self.get_argstring())
if r.status_code != 200:
exit(1)
# parse reply
reply = r.json()
assert isinstance(reply, list), "Unexpected type of reply: " + type(reply)
if len(reply) == 0:
break
for point in reply:
self.ignore_ids.append(point["place_id"])
# TODO use better name than "display_name", maybe add more info to Waypoint
self.gpxfile.waypoints.append(gpxpy.gpx.GPXWaypoint(latitude=point["lat"], longitude=point["lon"], name=point["display_name"]))
def save_to_disk(self):
with open(self.gpxfilename, "w") as f:
f.write(self.gpxfile.to_xml())
default_args = {
"q": "Camping",
"format": "json",
"limit": 50,
"use_boundingbox": False,
"boundingbox": [],
"outputfilename": "test.gpx",
"ignore_ids": [],
"maxsearchnums": 10,
"url": "https://nominatim.openstreetmap.org/search/",
}
if __name__ == "__main__":
# cli invocation goes here
# TODO: take user arguments and bring together with sensible defaults above
OSMSearch(default_args)