本文将记录有关利用百度地图API去搜索一个城市内的POI的相关内容
百度地图API服务说明见其主页:
http://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding
地址解析:根据地址获取坐标
http://api.map.baidu.com/geocoder?address=地址&output=json&key=用户密钥&city=城市名)
它返回的是个json类型数据,一个区域最大返回数为400,每页最大返回数为20
逆地址解析:根据坐标获取地址
http://api.map.baidu.com/geocoder?location=纬度,经度&output=输出格式类型&key=用户密钥
根据地址获取POI
http://api.map.baidu.com/place/v2/search?query=%E8%B6%85%E5%B8%82&page_size=0&page_num=2&scope=1®ion=%E6%98%8C%E9%BB%8E&output=json&ak=40bUQeFSGGs8c45LHMfe2Ram0hSCKZks
秘钥的申请在百度API的官方网站http://lbsyun.baidu.com/apiconsole/key
在这两个API中有关query类型的选择可以参考http://lbsyun.baidu.com/index.php?title=lbscloud/poitags这个网址内的类别。
接下来需要考虑的就是有关在地图内小方格的选择,参考了一些博文里面提到方格的大小选择是2KM*2KM的大小比较好,我是对一个县城进行搜索,所以将该县城分割为四份或者8份即够了。
1 区域划分,2km*2km的区域基本可以满足需求,获取每个区域的对角坐标(经纬度),逐行写入一个txt文本里
2 爬虫程序编写 读取1中的txt文本,逐行循环;调用百度API接口,爬取json;将爬取的数据存入数据库中; 每个类别跑一次程序
#该代码是学习其他博文,在此对其他博主表示感谢
import sys
import requests #导入requests库,这是一个第三方库,把网页上的内容爬下来用的
ty=sys.getfilesystemencoding() #这个可以获取文件系统的编码形式
import time
#百度API接口,通过输入经纬度范围查询范围内的POI数据,
#http://lbsyun.baidu.com/index.php?title=lbscloud/poitags 该网址为POI类型,即API链接中的query的类型
base_url='http://api.map.baidu.com/place/v2/search?query={}&bounds={}&page_size=20&page_num={}&output=json&ak=SAKipkD157dL2Mamat8D4FqgxzYz0x7X'
#1.获取每个格网起始URL
def get_begin_url(keyword,page=0):
with open('E:/贾学斌/格网矩形范围.txt', 'r') as f:
#网格矩形范围内每一行是一个小方格的经纬度范围,保存顺序为小方格的左下经度纬度、右上经度纬度
f=f.readlines()
for line in f:
w1 = float(line.split(',')[1])
j1 = float(line.split(',')[0])
w2 = float(line.split(',')[3])
j2 = float(line.split(',')[2])
url2 = base_url.format(keyword, str(w1) + ',' + str(j1) + ',' + str(w2) + ',' + str(j2), str(page))
yield url2
#2.解析起始URL,请求成功返回json数据
def parse_begin_url(url,keyword):
print(url)
html=requests.get(url)
time.sleep(3)
if html.status_code==200:
data = html.json()
# 每个经纬度的POI数据会只显示前400个,以后不再显示,如果当总数为400时,需要将范围缩小在进行一次搜索
if 400>data['total']>0:
print(data['total'])
page_numbers = int(data['total'] / 20) + 1
if page_numbers>=1:
write_to_file(data,keyword)
time.sleep(3)
if page_numbers>1:
for page in range(1,page_numbers):
url2=url.replace('page_num=0','page_num='+str(page))
res=requests.get(url2).json()
write_to_file(res,keyword)
time.sleep(3)
elif data['total']==400:
print('区域过大,准备分割')
urls=get_four_areas(url,keyword)
for url in urls:
parse_begin_url(url,keyword)
def get_four_areas(url,keyword):
#分割的原则是将输入的经纬度范围平均分成四份
areas=[]
boundary = url.split('=')[2].split('&')[0].split(',')
w1=float(boundary[0])
j1=float(boundary[1])
w2=float(boundary[2])
j2=float(boundary[3])
wei=(float(w2)-float(w1))/2
jing=(float(j2)-float(j1))/2
area1=[w1,j1,w1+wei,j1+jing]
area1=','.join([str(x) for x in area1])
area2=[w1,j1+jing,w1+wei,j2]
area2 = ','.join([str(x) for x in area2])
area3=[w1+wei,j1,w2,j1+jing]
area3 = ','.join([str(x) for x in area3])
area4=[w1+wei,j1+jing,w2,j2]
area4 = ','.join([str(x) for x in area4])
areas=[area1,area2,area3,area4]
for index,area in enumerate(areas):
url=base_url.format(keyword,area,str(0))
print('第'+str(index+1)+'个分割图形url:'+url)
yield url
def write_to_file(data,keyword):
for result in data['results']:
name = result['name']
lat = result['location']['lat']
lng = result['location']['lng']
address = result['address']
area=result['area']
city=result['city']
province=result["province"]
detail = result['detail']
uid = result['uid']
a = '#'.join([uid, name, address, str(lat), str(lng), str(detail),area,city,province])
with open('E:/贾学斌/{}.txt'.format(keyword), 'a') as f:
f.write(a + '\n')
print('写入成功')
with open('E:/贾学斌/昌黎县全部POI数据.txt', 'a') as f:
f.write(a + '\n')
print('写入成功')
def main():
keywords = ['百货商场', '超市', '便利店', '商铺', '集市', '通讯营业厅', '邮局', '物流公司', '公用事业', '公园', '风景区', '动物园', '植物园', '游乐园', '文物古迹', '度假村', '农家院', '休闲广场', '高等院校', '中学', '小学', '幼儿园', '特殊教育学校', '综合医院', '专科医院', '诊所', '药店', '飞机场', '火车站', '长途汽车站', '公交车站', '公交线路', '港口', '服务区', '收费站', '银行', '', '信用社', '投资理财', '中央机构', '各级政府', '行政单位', '政治教育机构', '福利机构', '高速公路出口', '高速公路入口', '机场出口', '机场入口', '车站出口', '车站入口', '岛屿', '山峰', '水系']
for keyword in keywords:
urls=get_begin_url(keyword)
for url in urls:
parse_begin_url(url,keyword)
if __name__=="__main__":
main()