Python+OSM 迅速获取全球矢量要素

拒绝手动下载,告别API限额:城市分析数据获取的最优雅方案。
还在到处求人找 GIS 数据?
想做城市分析,结果第一步就卡在“数据去哪下”:
- • 找 POI: 商业 API 各种限额,还要实名认证、写爬虫;
- • 找建筑轮廓: 搜了半天,下回来的却是几年前的“老黄历”。
对于 GIS 人来说,最耗时的往往不是空间分析,而是反复折腾数据下载。
🚀 生产力降维打击:OSMnx + Python
其实,全球最大的免费空间数据库 OpenStreetMap (OSM) 一直都在,而 Python 的库 OSMnx,已经可以把抓取过程彻底自动化。
不需要手动画范围,不需要网页一个个点,更不用低声下气求数据。
输入一个地名,脚本直接把道路、建筑、医院、公园、商场这些要素全部打包导出,且直接就是 ArcGIS、QGIS、GeoPandas 通用的矢量格式!
💻 实战:一键抓取杭州西湖区路网
以往你要在网页上切片下载的数据,现在只需要几行代码(运行前,需要安装 osmnx库,pip安装即可)。
import osmnx as oximport osdef download_xihu_roads(): # 1. 定义区域(支持中文地名) place_name = "西湖区, 杭州市, 浙江省, 中国" print(f"🚀 正在抓取 {place_name} 的路网数据...") try: # 2. 获取路网(driving 模式) graph = ox.graph_from_place(place_name, network_type='drive') # 3. 将图结构转为 GeoDataFrame (矢量数据) nodes, edges = ox.graph_to_gdfs(graph) # 4. 导出为 Shapefile output_folder = "xihu_roads_shp" if not os.path.exists(output_folder): os.makedirs(output_folder) # 处理 SHP 不支持 list 字段的兼容性问题 for col in edges.columns: if isinstance(edges[col].iloc[0], list): edges[col] = edges[col].apply(lambda x: ",".join(map(str, x))) edges_path = os.path.join(output_folder, "xihu_edges.shp") edges.to_file(edges_path, encoding='utf-8') print(f"✅ 下载成功!文件保存至: {edges_path}") except Exception as e: print(f"❌ 抓取失败: {e}")if __name__ == "__main__": download_xihu_roads()
运行结束,你得到的是一份带完整拓扑关系的道路 Shapefile,直接拖进 GIS 软件就能用!

🔍 深度进阶:你以为它只有路网?
很多 GIS 人以为 OSM 只能拿路网,那真是太低估它了。它更像是一个“全球众包空间数据库”。
只要 OSM 体系里存在的 Tags(标签),你都能抓。比如:
- • 城市底板: 建筑轮廓、水系、停车场、公园绿地;
- • 精细属性: 道路等级、单行线、建筑高度、商铺经营类目。
只需配置自定义标签:
custom_tags = { "building": True, # 所有建筑 "amenity": ["hospital", "cafe"], # 医院与咖啡馆 "landuse": ["forest", "park"] # 森林与公园}# 批量提取地理要素gdf = ox.geometries_from_place("西湖区, 杭州市, 中国", tags=custom_tags)
提示: 更多可抓取要素请参考 OSM Wiki 官方文档:(https://wiki.openstreetmap.org/wiki/Map_features)
欢迎转发给身边还在手动下数据的小伙伴!