如何使用 Python 和 Osmium 从 .osm.pbf 文件按标签过滤 OpenStreetmap 路径

在我们之前的文章如何使用 Python 和 osmium 读取 .osm.pbf 文件的最小示例中,我们研究了如何读取 .osm.pbf 文件并计算所有节点、路径和关系。

今天,我们将研究如何使用 osmium 处理 .osm.pbf 文件按标签过滤特定路径。在此示例中,我们将按 highway: trunk 过滤

filter_ways_osmium.py
#!/usr/bin/env python3
import osmium as osm
from collections import namedtuple
import itertools

Way = namedtuple("Way", ["id", "nodes", "tags"])

class FindHighwayTrunks(osm.SimpleHandler):
    """
    查找带有 "highway: trunk" 标签的路径
    """

    def __init__(self):
        osm.SimpleHandler.__init__(self)
        self.ways = []

    def way(self, way):
        # 如果此路径是 highway: trunk,...
        if way.tags.get("highway") == "trunk":
            # ... 将其添加到 self.ways
            # 注意:我们不能保留对 way 对象的引用,
            # 所以我们必须创建一个新的 Way 对象
            nodes = [node.ref for node in way.nodes]
            self.ways.append(Way(way.id, nodes, dict(way.tags)))

# 查找具有给定标签的路径
way_finder = FindHighwayTrunks()
way_finder.apply_file("kenya-latest.osm.pbf")

print(f"找到 {len(way_finder.ways)} 条路径")

此示例使用从 Geofabrik 下载的 kenya-latest.osm.pbf,但你可以使用任何 .osm.pbf 文件。在我的台式机上解析该文件大约需要 10 秒。

注意我们不能直接 self.ways.append(way),因为 way 是一个临时/内部 Protobuf 对象,不能直接使用。因此,我们创建自己的对象来包装提取的 way 内容:其 id、其 nodes 列表(节点 ID)和包含 tags 的字典。否则,你将看到此错误消息:

osmium_runtime_error.txt
Traceback (most recent call last):
  File "run.py", line 32, in <module>
    trunk_handler.apply_file("kenya-latest.osm.pbf")
RuntimeError: Way callback keeps reference to OSM object. This is not allowed.

Check out similar posts by category: Geography, Geoinformatics, OpenStreetMap, Python