如何使用 overpy 让 {{geocodeArea: xxx }} 查询在 python 中工作?
How to get a {{geocodeArea: xxx }} query to work in python using overpy?
我想使用 Overpass API 查找特定区域中的所有酒吧,并使用 geocodeArea 选择区域。
在 overpass-turbo.eu 上测试以下查询得到了我想要的结果:
{{geocodeArea:berlin}}->.searchArea;
(
node["amenity"="pub"](area.searchArea);
way["amenity"="pub"](area.searchArea);
relation["amenity"="pub"](area.searchArea);
);
out body;
>;
out skel qt;
但是当我在 python 中使用 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))
...我收到以下错误:
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.
我猜问题与双花括号有关,但到目前为止转义它们和其他变体并没有帮助。
Nominatim 的可能解决方案
感谢@scai,我现在知道,使用 {{geocodeArea:xxx}} overpass turbo 只会发出地理编码请求。我决定自己使用 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))
代码...
- 向 Nominatim 提出地理编码请求
- 搜索结果中的第一个元素(最多 3 个),它是一个关系
- 添加 3600000000 从关系 id 中获取区域 id
这不是一个非常干净的解决方案,我想知道是否可以直接将第一个结果(主要是城市作为点)用于我的目的。仍然欢迎提示。
{{geocodeArea: xxx }}
是 overpass turbo 的一个特殊功能,而不是 Overpass API 的一部分。 overpy 直接使用 Overpass API 这意味着你不能使用这个关键字。
但是 {{geocodeArea: xxx }}
只是告诉立交桥 turbo 执行 地理编码请求 ,即将地址转换为地理位置。你可以这样做,例如通过调用 Nominatim、Photon 或任何其他地理编码器。
您可以使用 area
过滤器而不是 geocodeArea
来获得类似的结果。例如:
area[name="Berlin"]->.searchArea;
(
node["amenity"="pub"](area.searchArea);
way["amenity"="pub"](area.searchArea);
relation["amenity"="pub"](area.searchArea);
);
out body;
>;
out skel qt;
这可能有效,但对于其他区域,您可能需要更具体地使用 area
过滤器中使用的标签,更多信息请参见 Language Guide for Overpass
我想使用 Overpass API 查找特定区域中的所有酒吧,并使用 geocodeArea 选择区域。
在 overpass-turbo.eu 上测试以下查询得到了我想要的结果:
{{geocodeArea:berlin}}->.searchArea;
(
node["amenity"="pub"](area.searchArea);
way["amenity"="pub"](area.searchArea);
relation["amenity"="pub"](area.searchArea);
);
out body;
>;
out skel qt;
但是当我在 python 中使用 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))
...我收到以下错误:
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.
我猜问题与双花括号有关,但到目前为止转义它们和其他变体并没有帮助。
Nominatim 的可能解决方案
感谢@scai,我现在知道,使用 {{geocodeArea:xxx}} overpass turbo 只会发出地理编码请求。我决定自己使用 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))
代码...
- 向 Nominatim 提出地理编码请求
- 搜索结果中的第一个元素(最多 3 个),它是一个关系
- 添加 3600000000 从关系 id 中获取区域 id
这不是一个非常干净的解决方案,我想知道是否可以直接将第一个结果(主要是城市作为点)用于我的目的。仍然欢迎提示。
{{geocodeArea: xxx }}
是 overpass turbo 的一个特殊功能,而不是 Overpass API 的一部分。 overpy 直接使用 Overpass API 这意味着你不能使用这个关键字。
但是 {{geocodeArea: xxx }}
只是告诉立交桥 turbo 执行 地理编码请求 ,即将地址转换为地理位置。你可以这样做,例如通过调用 Nominatim、Photon 或任何其他地理编码器。
您可以使用 area
过滤器而不是 geocodeArea
来获得类似的结果。例如:
area[name="Berlin"]->.searchArea;
(
node["amenity"="pub"](area.searchArea);
way["amenity"="pub"](area.searchArea);
relation["amenity"="pub"](area.searchArea);
);
out body;
>;
out skel qt;
这可能有效,但对于其他区域,您可能需要更具体地使用 area
过滤器中使用的标签,更多信息请参见 Language Guide for Overpass