【问题标题】:How to get a {{geocodeArea: xxx }} query to work in python using overpy?如何使用 overpy 让 {{geocodeArea: xxx }} 查询在 python 中工作?
【发布时间】:2019-10-02 08:23:51
【问题描述】:

我想使用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;

但是当我使用 overpy 在 python 中实现该查询时...

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 只会发出地理编码请求。我决定自己使用geopyNominatim 在我的程序中实现它:

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))

代码...

  1. 向 Nominatim 发出地理编码请求
  2. 搜索结果中的第一个元素(最多 3 个),它是一个关系
  3. 添加 3600000000 以从关系 id 中获取区域 id

这不是一个非常干净的解决方案,我想知道是否可以出于我的目的直接使用第一个结果(主要是城市)。仍然欢迎提示。

【问题讨论】:

    标签: python openstreetmap overpass-api


    【解决方案1】:

    {{geocodeArea: xxx }} 是 overpass turbo 的一个特殊功能,不是 Overpass API 的一部分。 overpy 直接使用 Overpass API,这意味着你不能使用这个关键字。

    但是{{geocodeArea: xxx }} 只是告诉 overpass turbo 执行 地理编码请求,即将地址转换为地理位置。你也可以这样做,例如通过调用 Nominatim、Photon 或任何其他地理编码器。

    【讨论】:

    • 感谢@scai 的回答!我现在通过我的 geopy 添加了一个 Nominatim 调用,它正在工作。唯一的问题是它的出价很笨拙,因为它需要在前几个结果中正确的城市关系。
    • @rayon 你介意分享你的实现吗?我正在尝试在我的代码中复制 geocodeArea 行为,虽然我成功了,但我发现在某些情况下它不会呈现相同的结果。
    • 嘿@CristianoDalbem,我最终得到的解决方案是我添加到问题末尾的代码。
    【解决方案2】:

    您可以使用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 中的 Overpass

    【讨论】:

      猜你喜欢
      • 2019-11-09
      • 2010-12-28
      • 2016-03-03
      • 2017-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多