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

如何补全OSM提取的瑞士学校数据中缺失的addr:city/addr:postcode标签?

处理瑞士OSM学校数据缺失地址字段的方案

问题背景

我使用包含瑞士OpenStreetMap数据的.pbf文件,通过以下Osmium命令提取所有带amenity=school,college标签的条目:

osmium tags-filter switzerland-exact.osm.pbf nwr/amenity=school,college \ 
    -o schools-in-switzerland.osm.pbf

将数据导出为JSON后用Python脚本处理,按addr:city→city、addr:postcode→postcode的规则转换格式,但部分学校缺失city或postcode字段。需要在提取或处理环节补全这些缺失标签,不局限于Osmium工具。


解决方案

1. 反向地理编码补全(Python处理阶段)

利用学校的经纬度坐标,通过OSM的地理编码服务反向查询所属城市和邮编,适合数据量不大的场景:

import json
import requests

def fetch_address(lat, lon):
    # 调用Nominatim反向地理编码接口,建议设置自定义User-Agent
    url = f"https://nominatim.openstreetmap.org/reverse?lat={lat}&lon={lon}&format=json&addressdetails=1"
    resp = requests.get(url, headers={"User-Agent": "SchoolDataTool/1.0"})
    if resp.status_code != 200:
        return {}
    addr = resp.json().get('address', {})
    # 适配不同层级的行政名称(城市/镇/村)
    return {
        'city': addr.get('city') or addr.get('town') or addr.get('village'),
        'postcode': addr.get('postcode')
    }

# 读取导出的学校JSON数据
with open('schools.json', 'r') as f:
    school_list = json.load(f)

# 遍历补全缺失字段
for school in school_list:
    if not school.get('city') or not school.get('postcode'):
        lat, lon = school.get('lat'), school.get('lon')
        if lat and lon:
            addr_data = fetch_address(lat, lon)
            if addr_data.get('city') and not school['city']:
                school['city'] = addr_data['city']
            if addr_data.get('postcode') and not school['postcode']:
                school['postcode'] = addr_data['postcode']

# 保存补全后的数据
with open('schools_complete.json', 'w') as f:
    json.dump(school_list, f, indent=2)

提示:数据量较大时,建议部署本地Nominatim实例,避免在线请求的速率限制。

2. 空间关联行政边界数据(预处理阶段)

先提取瑞士的行政边界数据,再通过空间匹配补全地址,适合批量处理:

步骤1:提取行政边界

# 提取admin_level=8(对应城市层级)和带postal_code标签的边界数据
osmium tags-filter switzerland-exact.osm.pbf r/admin_level=8 r/postal_code \
    -o switzerland-city-boundaries.osm.pbf

步骤2:用Geopandas做空间连接

import geopandas as gpd

# 读取学校点数据和行政边界多边形数据
schools = gpd.read_file('schools-in-switzerland.osm.pbf', layer='points')
boundaries = gpd.read_file('switzerland-city-boundaries.osm.pbf', layer='multipolygons')

# 空间匹配:找到每个学校所在的行政区域
merged = gpd.sjoin(schools, boundaries, how='left', predicate='within')

# 优先保留原地址标签,缺失时用行政边界的信息补全
merged['city'] = merged.apply(lambda x: x['addr:city'] if x['addr:city'] else x['name'], axis=1)
merged['postcode'] = merged.apply(lambda x: x['addr:postcode'] if x['addr:postcode'] else x['postal_code'], axis=1)

# 保存补全后的OSM数据
merged.to_file('schools_with_full_address.osm.pbf', driver='OSM')

3. 利用OSM关系继承地址

部分学校属于带地址标签的父节点(如建筑群),可通过提取关联关系补全:

步骤1:提取学校关联的关系数据

# 先导出学校的ID列表(OPL格式)
osmium tags-filter switzerland-exact.osm.pbf nwr/amenity=school,college --output-format=opl > school-ids.opl
# 根据ID提取关联的关系数据
osmium getid switzerland-exact.osm.pbf -i school-ids.opl --relations -o school-relations.osm.pbf

步骤2:Python解析关系补全地址

在脚本中解析关系数据,提取父节点的addr:city和addr:postcode标签,补全对应学校的缺失字段。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 16:17:48