I want to find all pubs in a specific area using the Overpass API and selecting the area with geocodeArea.
Testing the following query on overpass-turbo.eu gives me the desired result:
{{geocodeArea:berlin}}->.searchArea;
(
node["amenity"="pub"](area.searchArea);
way["amenity"="pub"](area.searchArea);
relation["amenity"="pub"](area.searchArea);
);
out body;
>;
out skel qt;
But when I implement that query in python using overpy...
import overpy
api = overpy.Overpass()
result = api.query("""
{{geocodeArea:berlin}}->.searchArea;
(
node["amenity"="pub"](area.searchArea);
way["amenity"="pub"](area.searchArea);
relation["amenity"="pub"](area.searchArea);
);
out body;
>;
out skel qt;
""")
print("Amenities in nodes: %d" % len(result.nodes))
print("Amenities in ways: %d" % len(result.ways))
... I get the following error:
Traceback (most recent call last):
File "testOP.py", line 15, in <module>
""")
File "/usr/local/lib/python2.7/dist-packages/overpy/__init__.py", line 119, in query
msgs=msgs
overpy.exception.OverpassBadRequest: Error: line 2: parse error: Unknown type "{"
Error: line 2: parse error: An empty query is not allowed
Error: line 2: parse error: ';' expected - '{' found.
I guess that the problem has to do with the double curly braces, but so far escaping them and other variations didn't help.
Possible solution with Nominatim
Thanks to @scai I know now, that with {{geocodeArea:xxx}} overpass turbo only makes a geocode request. I decided to implement that in my program by myself using geopy and Nominatim:
from geopy.geocoders import Nominatim
import overpy
city_name = "berlin"
# Geocoding request via Nominatim
geolocator = Nominatim(user_agent="city_compare")
geo_results = geolocator.geocode(city_name, exactly_one=False, limit=3)
# Searching for relation in result set
for r in geo_results:
print(r.address, r.raw.get("osm_type"))
if r.raw.get("osm_type") == "relation":
city = r
break
# Calculating area id
area_id = int(city.raw.get("osm_id")) + 3600000000
# Excecuting overpass call
api = overpy.Overpass()
result = api.query("""
area(%s)->.searchArea;
(
node["amenity"="pub"](area.searchArea);
way["amenity"="pub"](area.searchArea);
relation["amenity"="pub"](area.searchArea);
);
out body;
""" % area_id)
# Printing no. of pubs in nodes and ways
print("Amenities in nodes: %d" % len(result.nodes))
print("Amenities in ways: %d" % len(result.ways))
The code ...
- Does a geocoding request to Nominatim
- Searches for the first element in the results (max. 3) which is a relation
- Adds 3600000000 to get the area id from the relation id
It's not a very clean solution and I wonder if it's possible to directly use the first result (which is mostly the city just as point) for my purposes. Hints are still welcome.