使用Python獲取城市POI數(shù)據(jù)

1.數(shù)據(jù)接口:

本次使用百度地圖開放平臺中的地點檢索API來獲取城市POI數(shù)據(jù),此次以矩形區(qū)域檢索為例。

2.獲取思路:

因為百度出于數(shù)據(jù)保護目的,單次訪問服務(wù)最多同時返回400條數(shù)據(jù),不過官方也給出了解決方案,即通過添加分類、設(shè)置范圍等方式,從而縮小檢索范圍,滿足數(shù)據(jù)獲取要求。

要想獲取一個大的矩形區(qū)域內(nèi)的數(shù)據(jù),就需要先將大區(qū)域劃分成一個個的小區(qū)域,然后通過小區(qū)域范圍去訪問接口獲取數(shù)據(jù)。

3.代碼示例:

import requests
import json
import time
import pandas as pd

# 構(gòu)建URL訪問API部分
class BaiduPoi(object):
    def __init__(self, query, loc, ak):  # query:行業(yè)分類,loc:檢索的位置坐標,ak:服務(wù)秘鑰
        self.query = query
        self.loc = loc
        self.ak = ak

    # 構(gòu)建訪問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獲取數(shù)據(jù)
    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['一級行業(yè)'] = h1
                        js['二級行業(yè)'] = h2
                        js['name'] = item['name']
                        js['lat'] = item['location']['lat']
                        js['lng'] = item['location']['lng']
                        yield js
                else:
                    print(url)
                    print('本頁及以后無數(shù)據(jù)!')
                    break
            except:
                print('出現(xiàn)錯誤!')
                with open('./log.txt', 'a') as fl:
                    fl.write(url+'\n')


# 大網(wǎng)格劃分成小網(wǎng)格部分
class LocalDiv(object):
    def __init__(self, loc_all,
                 divd):  # loc_all:為構(gòu)建訪問url中的左下角(西南)坐標和右上角(東北)坐標(bounds=39.915,116.404,39.975,116.414);divd:分割網(wǎng)格大小
        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)

    # 劃分經(jīng)度
    def lng_all(self):
        lng_sw = float(self.loc_all.split(',')[1])  # 西南方向經(jīng)度
        lng_ne = float(self.loc_all.split(',')[3])  # 東北方向經(jīng)度
        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)

    # 將劃分的經(jīng)緯度進行組合
    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

    # 構(gòu)建每個小網(wǎng)格的西南和東北點的坐標對
    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__':
    # 行業(yè)劃分,根據(jù)需要可以自己構(gòu)建行業(yè)劃分標準
    pois = {'商業(yè)': ['酒店', '購物'....],
            '教育': ['高等院校', '中學(xué)', '小學(xué)', '幼兒園', ......],
            。。。。。。
            }
    print('----------開始爬取數(shù)據(jù)!----------')
    start_time = time.time()
    loc = LocalDiv('填寫要查詢的坐標范圍(例:31.131387,121.413508,31.343321,121.540564)', 0.01)  # 查詢范圍坐標,網(wǎng)格大小,現(xiàn)在采取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:  # 獲取二級行業(yè)
                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數(shù)據(jù)已經(jīng)爬取完畢,共耗時{:.2f}秒'.format(end_time - start_time))
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容