有时候,我们并不需要获取POI的具体位置,只需要知道有每个城市有多少种特定类型的POI即可,比如我们需要比较“星巴克”和“瑞幸咖啡”的门店在全国的布局差异时,又或者我们在进行城市级宏观研究时,可能需要把人均POI数量、POI密度或者POI数量作为一个影响因素进行分析。
针对这种特别的POI抓取需求,同样可以通过调用百度Place API进行实现,具体实现方式为首先调用Place API查全国范围的POI,获取北京、天津、重庆、上海四个直辖市的POI数量,然后多次调用Place API查各省的POI,获取特定省份下的各城市特定POI总量。实现该需求的easy版代码如下:
#-*-coding:utf-8-*-
#用于抓取除港澳台外国内所有地级及地级以上城市的指定POI数量
import json
import requests
import importlib,sys
import time
#python3中文编码,创建POI类方便输出
importlib.reload(sys)
class POI:
id=-1
province=''
city=''
num=-1
#参数设置区
#Query是关键字,Tag是POI类型,百度POI分类表为 http://lbsyun.baidu.com/index.php?title=lbscloud/poitags
inputKey='YourBAIDUKeySample1'
inputQuery='旅游景点'
inputTag='旅游景点'
outputPath='E:\\desktop\\'
#固定参数初始化
provValues=['河北省','山西省','辽宁省','吉林省','黑龙江省','江苏省','浙江省','安徽省','福建省','江西省','山东省','河南省','湖北省','湖南省','广东省','海南省','四川省','贵州省','云南省','陕西省','甘肃省','青海省','内蒙古自治区','广西壮族自治区','西藏自治区','宁夏回族自治区','新疆维吾尔自治区']
spcityValues=['北京市','上海市','天津市','重庆市']
poilist=list()
tid=1
t1=time.time()
#处理直辖市
url='http://api.map.baidu.com/place/v2/search?query='+inputQuery+'&tag='+inputTag+'®ion=全国&output=json&ak='+inputKey
response = requests.get(url)
data = json.loads(response.text)
for item in data['results']:
if item['name'] in spcityValues:
tpoi=POI()
tpoi.id=tid
tpoi.province=item['name']
tpoi.city=item['name']
tpoi.num=item['num']
poilist.append(tpoi)
tid += 1
print('直辖市处理完毕..')
#处理普通省或自治区下的城市
for i in range(len(provValues)):
print('处理'+provValues[i]+'中...')
url='http://api.map.baidu.com/place/v2/search?query='+inputQuery+'&tag='+inputTag+'®ion='+provValues[i]+'&output=json&ak='+inputKey
response = requests.get(url)
data = json.loads(response.text)
for item in data['results']:
tpoi=POI()
tpoi.id=tid
tpoi.province=provValues[i]
tpoi.city=item['name']
tpoi.num=item['num']
poilist.append(tpoi)
tid+=1
print('普通城市处理完毕')
t2=time.time()
#把结果写出到OSpider_Query_Tag.txt文件中
result_path=outputPath+'OSpider_'+inputQuery+'_'+inputTag+'.txt'
file = open(result_path, 'w')
file.write('-------------------------------OSpider_v.sp ---------------------------------------\n')
file.write('于 ' + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + ' 抓取除港澳台外国内所有地级及地级以上城市的指定POI数量\n')
file.write('抓取关键词:' + inputQuery + '\n')
file.write('POI类型:' + inputTag+ '\n')
file.write('使用的KEY:'+inputKey+'\n')
file.write('抓取耗时:'+str(t2-t1)+'s\n')
file.write('-------------------------------results----------------------------------------\n')
file.write('id\tprovince\tcity\tnum\n')
for each in poilist:
tstr = str(each.id)+ '\t' + each.province + '\t' + each.city + '\t' + str(each.num) + '\n'
file.write(tstr)
file.close()
print('写入完毕,输出路径:'+result_path)
上述代码未进行封装,且鲁棒性并不足够优秀。为了更方便且健壮的实现上述功能,建议使用开源项目OSpider中的POISpider.py,可以在项目主页获取源码。调用OSpider中的POISpider实现分城市获取POI总量的代码如下:
from POISpider import BaiduPOISpider
keylist=['YourBAIDUKeySample1','YouRbaiDuKEYsaMPlE2']
spider=BaiduPOISpider()
spider.set_key(keylist,thread_protect=3)
#测试分城市获取POI总量(check)
df=spider.getPOI_CityNum('高中','中学')
#输出结果至CSV文件
df.to_csv('分城POI总量_高中.csv', encoding='utf-8-sig')
如果完全不想写代码,也可以直接下载OSpider桌面软件,通过“分城市获取POI总量”功能刷刷刷地搞定。
功能:用于抓取除港澳台外国内所有地级及地级以上城市的指定POI数量并输出CSV/TXT格式文件。适用于宏观研究(把各城市的POI量作为指标)。
输入参数说明
参数####### | 说明 |
---|---|
POI名称 | 检索关键字。支持多个关键字并集检索,不同关键字间以 符 号 分 隔 , 最 多 支 持 10 个 关 键 字 检 索 。 如 : ” 银 行 符号分隔,最多支持10个关键字检索。如:”银行 符号分隔,最多支持10个关键字检索。如:”银行酒店”。如果需要按POI分类进行检索,请将分类通过“POI名称”参数进行设置,如“POI名称=咖啡厅”,此时POI类型建议留空。 |
[POI类型] | 检索分类偏好,可为空,多个分类以","分隔,如果需要严格按分类检索,请留空并设置POI名称为分类名。典型的POI类型使用场景为特定类型下按名称检索,如抓取名称中包括“鑫源”的便利店(POI名称=鑫源,POI类型=便利店) |
输出文件 | 结果文件的保存路径,支持输出为TXT(.txt),CSV(.csv) |
抓取结果属性说明
列名 | 说明 |
---|---|
provice | 省份名 |
city | 城市名 |
num | 该城市特定POI总量 |
注意事项
- 分城市获取POI总量所获得的值的与百度地图大比例尺下各城市指定POI数量标注是类似的,该值仅供参考,与具体抓取某城市POI的实际数量相比有时偏大有时偏小。
- OSpider尚不提供城市面文件,如有需要请根据城市名自行链接。
OSpider v3.0.0桌面版的核心功能为按行政区划名称、矩形框、圆形区和自定义面文件四种方式抓取POI(暂仅支持百度POI,高德POI将再下一次更新中加入),支持通过csv批处理文件批量执行POI抓取任务,且提供了分城市获取POI总量的实用工具。OSpider v3.0.0也集成了WGS84/BD09/GCJ02坐标互转工具与地址解析工具。
OSpider v3.0.0源码的功能模块包括POI抓取模块、坐标转换模块、行政区划获取模块、地址解析模块。