You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从OSM文件生成包含geometry列的DataFrame以支持QGIS矢量层导入

解决方案

核心原因说明

原方案仅提取了OSM要素的标签属性,未针对不同类型的OSM要素做几何解析:只有节点(Node)有elem.location属性,路径(Way)、关系(Relation)本身无该属性,因此直接追加elem.location无法获取全量要素的几何信息。

具体实现步骤

  • 第一步:先预解析OSM文件缓存所有节点的坐标,避免解析路径/关系时无法获取关联节点的经纬度
  • 第二步:分OSM要素类型生成对应几何对象,转成WKT格式存入DataFrame
  • 第三步:使用GeoPandas将带几何的DataFrame写入PostgreSQL,自动创建空间字段与索引

代码示例

import osmium
import pandas as pd
import geopandas as gpd
from shapely.geometry import Point, LineString, Polygon

# 节点坐标缓存处理器
class NodeCacheHandler(osmium.SimpleHandler):
    def __init__(self):
        super().__init__()
        self.node_cache = {}
    
    def node(self, n):
        self.node_cache[n.id] = (n.location.lon, n.location.lat)

# 带几何提取的OSM解析处理器
class OSMGeomParser(osmium.SimpleHandler):
    def __init__(self, node_cache):
        super().__init__()
        self.data_list = []
        self.node_cache = node_cache
    
    def node(self, n):
        # 提取节点类型要素的几何
        geom = Point(n.location.lon, n.location.lat)
        row = dict(n.tags)
        row.update({
            "osm_id": n.id,
            "osm_type": "node",
            "geometry": geom.wkt
        })
        self.data_list.append(row)
    
    def way(self, w):
        # 提取路径类型要素的几何
        try:
            coords = [self.node_cache[nd.ref] for nd in w.nodes]
        except KeyError:
            # 跳过关联节点缺失的无效路径
            return
        # 闭合路径判定为面,否则为线
        geom = Polygon(coords) if w.is_closed() else LineString(coords)
        row = dict(w.tags)
        row.update({
            "osm_id": w.id,
            "osm_type": "way",
            "geometry": geom.wkt
        })
        self.data_list.append(row)

# 执行解析
osm_path = "你的OSM文件路径.osm"
# 先缓存所有节点
cache_handler = NodeCacheHandler()
cache_handler.apply_file(osm_path)
# 再解析全量要素带几何
geom_parser = OSMGeomParser(cache_handler.node_cache)
geom_parser.apply_file(osm_path)

# 生成带WKT几何列的DataFrame
df = pd.DataFrame(geom_parser.data_list)
# 转成GeoDataFrame指定坐标系为WGS84(EPSG:4326)
gdf = gpd.GeoDataFrame(
    df,
    geometry=gpd.GeoSeries.from_wkt(df["geometry"]),
    crs="EPSG:4326"
)

# 写入PostgreSQL,自动创建空间字段
gdf.to_postgis(
    name="你的目标表名",
    con="postgresql://用户名:密码@地址:端口/数据库名",
    if_exists="replace",
    index=False
)

后续操作说明

写入完成后直接在QGIS中连接对应PostgreSQL数据库,选择该表即可自动识别geometry列为几何字段,无需额外配置坐标参考信息。

内容的提问来源于stack exchange,提问作者George

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 19:36:03