OSMNx技术问询:如何用本地OSM XML替代Overpass API获取街道网络
加载本地OSM文件批量处理道路网络查询
步骤1:获取覆盖所有查询区域的本地OSM文件
- 先统计你1000次查询的所有经纬度点,算出包含所有点的边界范围(取所有点的最大/最小经纬度)
- 导出对应区域的OSM文件,推荐用
.osm.pbf格式(体积更小、加载更快),直接从OSM官方的导出工具选边界框生成即可
步骤2:用OSMnx加载本地文件构建完整道路图
根据你保存的文件格式,选择对应的加载方法,同时可以直接应用你的自定义道路过滤规则:
import osmnx as ox # 加载.osm格式文件 G_full = ox.graph_from_xml( filepath="your_local_map.osm", custom_filter=road_filter, simplify=False, retain_all=True ) # 或者加载.osm.pbf格式(需先安装osmium:pip install osmium) G_full = ox.graph_from_pbf( filepath="your_local_map.osm.pbf", custom_filter=road_filter, simplify=False, retain_all=True )
步骤3:在本地大图上批量执行点查询
原来的graph_from_point是远程拉取局部数据,现在可以直接在已加载的大图上截取目标范围的子图,重复1000次也不会有网络开销:
import geopandas as gpd # 假设你的1000个点存在列表里:points = [(lat1, lng1), (lat2, lng2), ...] points = [...] # 大图只需要加载一次,后续循环处理每个点 for lat, lng in points: # 把经纬度点转为GeoDataFrame,方便生成缓冲范围 point = gpd.GeoDataFrame( {'geometry': [ox.geometry.Point(lng, lat)]}, crs="EPSG:4326" ) # 生成20米缓冲范围(先转米单位坐标系再缓冲,再转回WGS84) point_proj = point.to_crs("EPSG:3857") buffer_area = point_proj.buffer(20).to_crs("EPSG:4326") # 从大图中截取缓冲范围内的子图 G_sub = ox.graph_from_polygon( buffer_area.iloc[0], retain_all=True, simplify=False, graph=G_full ) # 在这里处理你的子图业务逻辑 # ...
核心优化点
- 单次加载大图:避免重复读取本地文件,所有查询基于内存中的完整图,大幅提升效率
- 优先用PBF格式:比XML格式的.osm文件加载速度快3-5倍,内存占用也更低
- 提前过滤道路:加载时就应用
custom_filter,减少大图的节点和边数量,后续子图截取会更高效
内容的提问来源于stack exchange,提问作者aman
相关产品推荐
相关产品推荐

