百度地图POI数据获取

  • Post author:
  • Post category:其他


事先声明,本人小白一枚,第一次写博客,对地理信息系统这方面基本不了解,因最近在一个规划公司实习,想整理一下做过的一些项目,参考了很多人的代码,也看到一些人需要这方面的代码,网上的一些代码都是Python2的,和Python3有一点区别,比如Python3中urllib2已经合并为了urllib,但函数基本都还是有的,需要大家去找一找。不喜勿喷!!!!


  1. 首先说明一下,什么是POI:

    POI是“Point of Interest”的缩写,中文翻译叫兴趣点,在地理信息系统中,一个POI可以是一栋房子、一个商铺、一个邮筒、一个公交站等。

    而我要做的呢就是利用百度地图提供的API接口获取某一类型的POI,比如餐饮、公交站等(虽然我不知道这些数据能用了来干嘛,像我们专业做分析都是抓评论的。。)

  2. 百度地图API:

    要想用百度地图的API,是需要申请产品密钥的,这个比较容易。登录百度账号,在百度地图开发者平台的API控制台申请一个服务端的AK。应用名称任意,IP白名单就0.0.0.0/0就可以。

这里写图片描述

但是你这个申请的秘钥还不能获取很多数据,要想获取,需要进一步申请认证

http://lbsyun.baidu.com/apiconsole/record


(证件一定要清晰)。

拿到AK以后就可以进行后续操作了。

  1. 怎么爬取

    要知道,每个区域爬取POI数目上限是400,也就是说,如果你要爬取的区域内的POI数目大于400,就只能获取400,所以我们要对区域进行划分,让每个区域内POI数目在400以内,这样就不会了。这里我们用矩形检索,主要请求参数是query查询的类别、bounds查询区域的左下、右上经纬度。lat,lng(左下角坐标),lat,lng(右上角坐标)。将查询得到json格式的数据,解码为utf-8编码方式后存储在content中

    大致就是这样:

    http://api.map.baidu.com/place/v2/search?query=%E8%A5%BF%E9%A4%90&bounds=23.1121,113.4408,23.212100000000003,113.5408&page_size=20&page_num=0&output=json&ak=

    (你的API秘钥)

    然后我们将这个大矩形划分为若干小矩形就OK了。

    好了,废话不多少上代码:

代码块

import json
from urllib.request import urlopen
import time
from urllib import request

def urls(itemy, loc):
    #baidu_api = "你的秘钥"
    urls=[]
    for page in range(0,20):
        url = "http://api.map.baidu.com/place/v2/search?query=" + request.quote(itemy) + "&bounds=" + loc 
        url = url + "&page_size=20&page_num=" + str(page) + "&output=json&ak=你的秘钥"
        urls.append(url)

    return urls

def baidu_search(urls):
    try:
        json_sel = []   
        for url in urls:
            req = request.Request(url)
            json_obj = urlopen(req)
            data = json.load(json_obj)

            for item in data['results']:
                jname = item["name"]
                jlat = item["location"]["lat"]
                jlng = item["location"]["lng"]
                if "telephone" in item:
                    jtel = item["telephone"].replace(',',' ')
                else:
                    jtel = ''

                js_sel = jname + ',' + str(jlat) + ',' + str(jlng) + ',' + str(jtel)
                json_sel.append(js_sel)
    except:
        pass

    return json_sel

def lat_all(loc_all):
    lat_sw = float(loc_all.split(',')[0])
    lat_ne = float(loc_all.split(',')[2])
    lat_list = []

    for i in range(0, int((lat_ne - lat_sw ) / 0.01)):  # 网格大小,可根据区域内POI数目修改
        lat_list.append(lat_sw + 0.01 * i)  
    lat_list.append(lat_ne)

    return lat_list

def lng_all(loc_all):
    lng_sw = float(loc_all.split(',')[1])
    lng_ne = float(loc_all.split(',')[3])
    lng_list = []
    for i in range(0, int((lng_ne - lng_sw ) / 0.01)): 
        lng_list.append(lng_sw + 0.01 * i)                      
    lng_list.append(lng_ne)

    return lng_list

def ls_com(loc_all):
    l1 = lat_all(loc_all)
    l2 = lng_all(loc_all)
    ab_list = []
    for i1 in range(0, len(l1)):
        a = str(l1[i1])
        for i2 in range(0, len(l2)):
            b = str(l2[i2])
            ab = a + ',' + b
            ab_list.append(ab)
    return ab_list   

def ls_row(loc_all):
    l1 = lat_all(loc_all)
    l2 = lng_all(loc_all)
    ls_com_v = ls_com(loc_all)
    ls = []
    for n in range(0, len(l1) - 1):
        for i in range(0 + len(l1) * n, len(l2) + (len(l2)) * n - 1):
            a = ls_com_v[i]
            b = ls_com_v[i + len(l2) + 1]
            ab = a + ',' + b
            ab_list = ab.split(',')
            if (ab_list[0] < ab_list[2] and ab_list[1] < ab_list[3]):
                ls.append(ab)


    return ls

if __name__ == '__main__':
    print("开始爬取数据,请稍等...")
    start_time = time.time()
    loc = '23.1121, 113.3408, 23.1475, 113.3902'
    locs_to_use = ls_row(loc)
    i = 0
    num = []
    filepath = '你的路径\政府.txt'
    f = open(filepath, 'w',encoding='utf-8')
    for loc_to_use in locs_to_use:
        print(loc_to_use)
        i += 1
        print("正在采集第%d个区域"%i)
        par = urls(u'政府', loc_to_use)
        print(par)
        a = baidu_search(par)
        b = len(a)
        num.append(b)
        print("第%d个区域采集数量为%d"%(i,b))

        for ax in a:
            print('政府,' + ax)
            item = '政府,' + ax
            f.write(item)
            f.write("\n")

    end_time = time.time()
    print("爬取完毕,用时%.2f秒" % (end_time - start_time))

好了,以上代码是在参考前人的基础上修改的,本人在Python以及爬虫上还是小白,如有问题,欢迎指正。

另外,代码中有一些输出是给我自己看的,比如区域内的POI数目,这个我是为了调控网格大小的,还有就是说一下

request.quote()是将ASCII码转换为URL编码的,这里烦了我好久,踩得比较深的坑。



版权声明:本文为weixin_38313931原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。