使用Python获取城市POI数据

1.数据接口:

本次使用百度地图开放平台中的地点检索API来获取城市POI数据,此次以矩形区域检索为例。

2.获取思路:

因为百度出于数据保护目的,单次访问服务最多同时返回400条数据,不过官方也给出了解决方案,即通过添加分类、设置范围等方式,从而缩小检索范围,满足数据获取要求。

要想获取一个大的矩形区域内的数据,就需要先将大区域划分成一个个的小区域,然后通过小区域范围去访问接口获取数据。

3.代码示例:

import requests
import json
import time
import pandas as pd

# 构建URL访问API部分
class BaiduPoi(object):
    def __init__(self, query, loc, ak):  # query:行业分类,loc:检索的位置坐标,ak:服务秘钥
        self.query = query
        self.loc = loc
        self.ak = ak

    # 构建访问URL
    def urls(self):
        urls = []
        for i in range(0, 20):
            url = 'http://api.map.baidu.com/place/v2/search?query=' + self.query + '&bounds=' + self.loc + '&page_size=20&page_num=' + str(
                i) + '&output=json&ak=' + self.ak
            urls.append(url)
        return urls

    # 访问APIP获取数据
    def get_data(self):
        for i, url in enumerate(self.urls()):
            try:
                # print(i,url)
                js = requests.get(url).text
                data = json.loads(js)
                if data['total'] != 0:
                    for item in data['results']:
                        js = {}
                        js['一级行业'] = h1
                        js['二级行业'] = h2
                        js['name'] = item['name']
                        js['lat'] = item['location']['lat']
                        js['lng'] = item['location']['lng']
                        yield js
                else:
                    print(url)
                    print('本页及以后无数据!')
                    break
            except:
                print('出现错误!')
                with open('./log.txt', 'a') as fl:
                    fl.write(url+'\n')


# 大网格划分成小网格部分
class LocalDiv(object):
    def __init__(self, loc_all,
                 divd):  # loc_all:为构建访问url中的左下角(西南)坐标和右上角(东北)坐标(bounds=39.915,116.404,39.975,116.414);divd:分割网格大小
        self.loc_all = loc_all
        self.divd = divd

    # 划分纬度
    def lat_all(self):
        lat_sw = float(self.loc_all.split(',')[0])  # 西南方向纬度
        lat_ne = float(self.loc_all.split(',')[2])  # 东北方向纬度
        lat_list = [str(lat_ne)]
        while lat_ne - lat_sw > 0:
            m = lat_ne - self.divd
            lat_ne = lat_ne - self.divd
            lat_list.append("{:.2f}".format(m))
        return sorted(lat_list)

    # 划分经度
    def lng_all(self):
        lng_sw = float(self.loc_all.split(',')[1])  # 西南方向经度
        lng_ne = float(self.loc_all.split(',')[3])  # 东北方向经度
        lng_list = [str(lng_ne)]
        while lng_ne - lng_sw > 0:
            m = lng_ne - self.divd
            lng_ne = lng_ne - self.divd
            lng_list.append("{:.2f}".format(m))
        return sorted(lng_list)

    # 将划分的经纬度进行组合
    def ls_com(self):
        lat = self.lat_all()
        lng = self.lng_all()
        latlng_list = []
        for i in range(0, len(lat)):
            a = lat[i]
            for i2 in range(0, len(lng)):
                b = lng[i2]
                ab = a + ',' + b
                latlng_list.append(ab)
        return latlng_list

    # 构建每个小网格的西南和东北点的坐标对
    def ls_row(self):
        lat = self.lat_all()
        lng = self.lng_all()
        latlng_list = self.ls_com()
        ls = []
        for n in range(0, len(lat) - 1):
            for i in range(len(lng) * n, len(lng) * (n + 1) - 1):
                coor_a = latlng_list[i]
                coor_b = latlng_list[i + len(lng) + 1]
                coor = coor_a + ',' + coor_b
                ls.append(coor)
        return ls


if __name__ == '__main__':
    # 行业划分,根据需要可以自己构建行业划分标准
    pois = {'商业': ['酒店', '购物'....],
            '教育': ['高等院校', '中学', '小学', '幼儿园', ......],
            。。。。。。
            }
    print('----------开始爬取数据!----------')
    start_time = time.time()
    loc = LocalDiv('填写要查询的坐标范围(例:31.131387,121.413508,31.343321,121.540564)', 0.01)  # 查询范围坐标,网格大小,现在采取0.01度进行分割
    locs_to_use = loc.ls_row()
    for h1, v in pois.items():
        print('爬取:', h1)
        file_name = './baidu_poi_{}.csv'.format(h1)
        for loc in locs_to_use:
            for h2 in v:  # 获取二级行业
                par = BaiduPoi(h2, loc, ak='ak值')
                dt = par.get_data()
                df = pd.DataFrame(dt)
                if len(df) != 0:
                    print(df)
                    df.to_csv(file_name,header=0,index=False,encoding='utf_8_sig',mode='a+')
                    time.sleep(1)
                else:
                    pass
    end_time = time.time()
    print('所有poi数据已经爬取完毕,共耗时{:.2f}秒'.format(end_time - start_time))
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容