基于Python实现地址周边500米内设施数量查询的高效方案
免费实现地址周边POI统计的最简方案
针对你的需求,推荐基于**OpenStreetMap(OSM)**的免费工具链,无需付费API,用Python基础库就能快速实现,步骤如下:
1. 地址转经纬度(地理编码)
用OSM的Nominatim服务,通过geopy库调用,无需API密钥(但要设置合法的User-Agent标识你的应用)。
安装依赖
pip install geopy requests
地理编码函数示例
from geopy.geocoders import Nominatim import time def get_coordinates(address): geolocator = Nominatim(user_agent="your_app_name_here") # 替换成你的应用名称 try: location = geolocator.geocode(address, timeout=10) return (location.latitude, location.longitude) if location else None except Exception as e: print(f"地址解析失败:{e}") time.sleep(1) # 避免请求过于频繁触发限制 return None
2. 查询500米范围内的POI数量
用OSM的Overpass API,通过自定义查询语句筛选指定类型的POI:
- 学校:
amenity=school - 公园:
leisure=park/landuse=recreation_ground(覆盖大多数公园类型) - 商铺:
shop=*(所有带shop标签的场所,包含超市、便利店等)
POI查询函数示例
import requests def count_pois(lat, lon, radius=500): # Overpass QL 查询语句:按坐标范围和标签筛选POI overpass_query = f""" [out:json]; ( node["amenity"="school"](around:{radius},{lat},{lon}); way["amenity"="school"](around:{radius},{lat},{lon}); relation["amenity"="school"](around:{radius},{lat},{lon}); node["leisure"="park"](around:{radius},{lat},{lon}); way["leisure"="park"](around:{radius},{lat},{lon}); relation["leisure"="park"](around:{radius},{lat},{lon}); node["landuse"="recreation_ground"](around:{radius},{lat},{lon}); way["landuse"="recreation_ground"](around:{radius},{lat},{lon}); relation["landuse"="recreation_ground"](around:{radius},{lat},{lon}); node["shop"](around:{radius},{lat},{lon}); way["shop"](around:{radius},{lat},{lon}); relation["shop"](around:{radius},{lat},{lon}); ); out count; """ response = requests.get("https://overpass-api.de/api/interpreter", params={"data": overpass_query}) if response.status_code == 200: data = response.json() elem = data["elements"] return { "学校": elem[0]["tags"]["total"] if len(elem) >0 else 0, "公园": elem[1]["tags"]["total"] if len(elem) >1 else 0, "商铺": elem[2]["tags"]["total"] if len(elem) >2 else 0 } else: print(f"POI查询失败:{response.status_code}") return {"学校":0, "公园":0, "商铺":0}
3. 批量处理地址列表
address_list = ["北京市海淀区中关村大街1号", "上海市浦东新区陆家嘴环路1000号"] # 替换成你的地址列表 for addr in address_list: coords = get_coordinates(addr) if coords: poi_counts = count_pois(coords[0], coords[1]) print(f"地址:{addr}") print(f"500米内POI数量:学校{poi_counts['学校']},公园{poi_counts['公园']},商铺{poi_counts['商铺']}\n") else: print(f"地址:{addr} 无法解析坐标\n")
注意事项
- Nominatim和Overpass API都有请求频率限制,批量处理时建议添加1-2秒的延时,避免被封禁
- OSM的数据覆盖度在国内部分城市可能不如商业API,但足够满足基础需求
- 如果需要更精准的商铺分类,可以调整
shop标签的具体值(比如shop=supermarket只统计超市)
内容的提问来源于stack exchange,提问作者AlexKotov
相关产品推荐
相关产品推荐

