尧图精选

Python爬虫进阶实战:高德/百度地图API批量采集周边POI商户数据

🕒 发布时间:2026/10/1 19:00:08 📁 来源:尧图网络
在做线下门店选址、商圈分析、竞品调研这类业务场景时周边商户的POI数据是核心参考依据。手动逐个搜索不仅效率极低也很难做到全量覆盖。通过高德、百度地图开放平台的官方API结合Python实现批量自动化采集可以高效获取标准化的POI数据大幅提升数据获取效率。本文基于高德和百度地图的公开API完整实现周边商户POI的批量采集覆盖网格切分突破数量限制、分页拉取、自动去重、数据清洗、Excel导出全流程同时整理了实际开发中常见的坑点与解决方案。一、前期准备与整体方案1.1 技术栈说明只用基础库即可完成无需复杂依赖requests负责API接口的HTTP请求pandas负责结构化数据处理、去重与导出math负责经纬度网格切分计算time负责请求间隔控制与限流规避json负责接口返回数据解析1.2 API密钥申请两个平台的API都需要先申请密钥步骤基本一致进入对应地图开放平台官网注册开发者账号创建应用选择「Web服务」类型的密钥开通「周边搜索」相关的接口权限复制生成的密钥填入代码配置项两个平台都有免费调用额度个人学习和小规模使用基本足够大批量采集建议购买官方额度避免触发限流。1.3 整体实现流程采集参数配置目标区域网格切分单网格分页调用API数据解析与字段提取跨网格数据去重数据清洗与格式标准化Excel文件导出二、核心原理与接口说明2.1 为什么要做网格切分这是批量采集中最关键的一个点。地图API的周边搜索接口都有返回数量上限高德单次周边搜索最多返回1000条结果百度最多返回760条。如果直接在大范围内调用核心区域的大量POI会被截断无法获取全量数据。最开始做的时候图省事直接用5公里大半径调用结果发现核心商圈的店铺缺了近一半后来才知道有返回上限踩了不小的坑。解决方案就是把目标区域按经纬度切分成若干个小网格每个网格的半径控制在返回结果不超过上限的范围内逐个网格采集后再合并去重就能实现大范围的全量POI获取。2.2 高德地图周边搜索API接口地址[https://restapi.amap.com/v3/place/around](https://restapi.amap.com/v3/place/around)核心请求参数key开发者密钥location中心点经纬度格式为「经度,纬度」keywords搜索关键词如“餐饮”“酒店”radius搜索半径单位米最大50000offset单页返回数量最大25page页码extensions返回结果控制base返回基本信息all返回详细信息2.3 百度地图周边搜索API接口地址[https://api.map.baidu.com/place/v2/search](https://api.map.baidu.com/place/v2/search)核心请求参数ak开发者密钥query搜索关键词location中心点经纬度格式为「纬度,经度」radius搜索半径单位米page_size单页返回数量最大20page_num页码output返回格式选json这里踩过第二个坑两个平台的经纬度顺序是反的高德是经度在前百度是纬度在前一开始没注意的时候返回的结果全是错位的调了半天才发现是参数顺序的问题。三、分步代码实现3.1 配置项与网格切分工具先定义基础配置和通用工具函数核心是经纬度网格切分的实现。importrequestsimportpandasaspdimportmathimporttime# 配置项 # 高德配置AMAP_KEY你的高德开发者Key# 百度配置BAIDU_AK你的百度开发者AK# 采集参数KEYWORD便利店# 目标区域[西南经度, 西南纬度, 东北经度, 东北纬度]BOUNDS[116.30,39.90,116.50,40.05]# 示例北京部分区域# 网格步长单位度数值越小网格越密数据越全但速度越慢GRID_STEP0.02# 单网格搜索半径单位米配合步长设置RADIUS1500# 请求间隔单位秒SLEEP_TIME0.2网格切分函数根据输入的区域边界和步长生成所有网格的中心点经纬度defgenerate_grid_points(bounds,step): 根据区域边界生成网格中心点列表 :param bounds: [西南经度, 西南纬度, 东北经度, 东北纬度] :param step: 网格步长单位度 :return: 中心点经纬度列表 [(lon, lat), ...] min_lon,min_lat,max_lon,max_latbounds points[]lon_stepsmath.ceil((max_lon-min_lon)/step)lat_stepsmath.ceil((max_lat-min_lat)/step)foriinrange(lon_steps1):forjinrange(lat_steps1):lonmin_loni*step latmin_latj*stepiflonmax_lonandlatmax_lat:points.append((round(lon,6),round(lat,6)))print(f共生成{len(points)}个网格中心点)returnpoints3.2 高德地图POI采集实现封装单页采集函数再实现批量分页与网格遍历deffetch_amap_poi(lon,lat,keyword,radius,page):采集单页高德POI数据url[https://restapi.amap.com/v3/place/around](https://restapi.amap.com/v3/place/around)params{key:AMAP_KEY,location:f{lon},{lat},keywords:keyword,radius:radius,offset:25,page:page,extensions:base}try:resprequests.get(url,paramsparams,timeout10)resp.raise_for_status()dataresp.json()ifdata.get(status)!1:print(f高德接口报错{data.get(info)})return[]returndata.get(pois,[])exceptExceptionase:print(f请求失败{str(e)})return[]defcollect_amap_all(keyword,bounds,step,radius):高德全量POI采集网格切分分页拉取grid_pointsgenerate_grid_points(bounds,step)all_pois[]foridx,(lon,lat)inenumerate(grid_points):print(f正在采集第{idx1}/{len(grid_points)}个网格{lon},{lat})page1whileTrue:poisfetch_amap_poi(lon,lat,keyword,radius,page)ifnotpois:breakall_pois.extend(pois)# 达到单页最大数量时继续翻页不足则停止iflen(pois)25:breakpage1time.sleep(SLEEP_TIME)time.sleep(SLEEP_TIME)print(f原始采集完成共获取{len(all_pois)}条数据)returnall_pois3.3 百度地图POI采集实现百度的逻辑和高德基本一致重点注意参数名和经纬度顺序的区别deffetch_baidu_poi(lon,lat,keyword,radius,page):采集单页百度POI数据url[https://api.map.baidu.com/place/v2/search](https://api.map.baidu.com/place/v2/search)params{ak:BAIDU_AK,query:keyword,location:f{lat},{lon},# 百度是纬度在前radius:radius,page_size:20,page_num:page,output:json}try:resprequests.get(url,paramsparams,timeout10)resp.raise_for_status()dataresp.json()ifdata.get(status)!0:print(f百度接口报错{data.get(message)})return[]returndata.get(results,[])exceptExceptionase:print(f请求失败{str(e)})return[]defcollect_baidu_all(keyword,bounds,step,radius):百度全量POI采集网格切分分页拉取grid_pointsgenerate_grid_points(bounds,step)all_pois[]foridx,(lon,lat)inenumerate(grid_points):print(f正在采集第{idx1}/{len(grid_points)}个网格{lon},{lat})page0whileTrue:poisfetch_baidu_poi(lon,lat,keyword,radius,page)ifnotpois:breakall_pois.extend(pois)iflen(pois)20:breakpage1time.sleep(SLEEP_TIME)time.sleep(SLEEP_TIME)print(f原始采集完成共获取{len(all_pois)}条数据)returnall_pois3.4 数据去重与清洗网格重叠会产生大量重复数据需要根据POI唯一ID去重再做字段标准化defclean_poi_data(raw_pois,platformamap):POI数据去重与字段清洗ifnotraw_pois:returnpd.DataFrame()cleaned[]forpoiinraw_pois:ifplatformamap:locationpoi.get(location,).split(,)item{POI_ID:poi.get(id),名称:poi.get(name),类型:poi.get(type),地址:poi.get(address),经度:location[0]iflocationelse,纬度:location[1]iflocationelse,电话:poi.get(tel),省份:poi.get(pname),城市:poi.get(cityname),区县:poi.get(adname)}elifplatformbaidu:locationpoi.get(location,{})item{POI_ID:poi.get(uid),名称:poi.get(name),类型:poi.get(category),地址:poi.get(address),经度:location.get(lng),纬度:location.get(lat),电话:poi.get(telephone),省份:poi.get(province),城市:poi.get(city),区县:poi.get(area)}cleaned.append(item)dfpd.DataFrame(cleaned)# 根据官方ID去重比按名称去重准确得多before_countlen(df)df.drop_duplicates(subsetPOI_ID,keepfirst,inplaceTrue)after_countlen(df)print(f去重完成移除{before_count-after_count}条重复数据剩余{after_count}条)df.reset_index(dropTrue,inplaceTrue)returndf3.5 导出Excel最后把清洗好的数据导出为Excel方便后续分析使用defexport_to_excel(df,keyword,platform):导出为Excel文件filenamef{platform}_POI_{keyword}.xlsxdf.to_excel(filename,indexFalse,sheet_namePOI明细)print(f数据已导出至{filename})主函数调用示例if__name____main__:# 高德采集示例raw_datacollect_amap_all(KEYWORD,BOUNDS,GRID_STEP,RADIUS)clean_dfclean_poi_data(raw_data,platformamap)export_to_excel(clean_df,KEYWORD,高德)# 百度采集示例# raw_data collect_baidu_all(KEYWORD, BOUNDS, GRID_STEP, RADIUS)# clean_df clean_poi_data(raw_data, platformbaidu)# export_to_excel(clean_df, KEYWORD, 百度)四、常见问题与避坑指南4.1 接口返回权限错误检查密钥是否正确有没有复制多余空格确认应用类型是否正确Web服务API不能用浏览器端的密钥查看对应接口是否已经开通权限部分高级接口需要单独申请检查是否超出当日调用配额超出后会返回报错4.2 返回结果数量明显偏少检查网格步长和搜索半径是否匹配步长太大导致区域覆盖不全确认关键词是否准确部分分类关键词需要用平台的标准分类词查看是否已经翻到最大页数高德最多返回1000条百度最多760条超出的话必须缩小网格部分偏远区域本身POI数量少属于正常情况4.3 坐标偏移问题两个平台的坐标体系不一样高德使用GCJ-02火星坐标系百度使用BD-09百度坐标系如果需要统一坐标需要做坐标转换。两个平台都提供了官方坐标转换API也可以自己实现转换算法注意不要直接用WGS84的经纬度去调用会出现几百米的偏移。4.4 触发限流与封禁严格控制请求频率不要短时间内大量请求免费额度用完后会返回超限错误等待次日重置或者购买额度不建议使用多线程并发请求很容易触发风控导致密钥临时封禁大批量采集建议使用多个密钥轮询或者拉长请求间隔4.5 数据重复或遗漏网格步长和搜索半径要配合设置半径要略大于网格的对角线避免出现缝隙重叠区域产生的重复数据通过POI_ID去重即可不要用名称去重容易误删同名店铺边界区域建议适当扩大采集范围再按目标区域裁剪避免边缘数据遗漏五、总结与扩展思路本文基于高德和百度地图的官方API实现了大范围POI数据的批量采集通过网格切分的方式解决了单接口返回数量上限的问题完整覆盖从参数配置、数据拉取、去重清洗到导出的全流程。如果需要进一步扩展能力可以尝试这几个方向多关键词批量采集一次性获取多个品类的POI数据加入坐标转换功能统一两个平台的数据坐标体系接入数据库存储实现增量采集与定期更新结合可视化库生成POI分布热力图扩展多边形区域采集适配不规则的商圈或行政区边界
上一篇/下一篇内容由系统自动关联 返回资讯列表 →