首頁>資訊>

前言

昨天在網上瞎逛的時候,看到了一個概念——交通生活圈,經過一番查閱後,約模知道了它的意思:在現有交通狀況下,在一定的時間內乘坐現有交通工具你能抵達的範圍(ps.通常是指駕車)。 簡單來說,就是:“30分鐘內你能走多遠?” 正好某德地圖上也有類似的資料,效果如下:

它包含了20分鐘、30分鐘、45分鐘、60分鐘、90分鐘這5類資料,它範圍即對應的交通生活圈。感覺很厲害的鴨子~

於是,我決定自己探索一番…

一、獲取資料1. 交通生活圈資料

開啟瀏覽器的F12除錯工具,監聽網路請求:

其介面地址為:

https://report.amap.com/ajax/life/circle.do

有3個引數,對應的說明如下:

引數

說明

那麼,可以定義獲取資料的函式:

def get_data(disID):    '''    獲得交通生活圈資料    '''    url = 'https://report.amap.com/ajax/life/circle.do'    headers = {        'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0',        'Accept': 'application/json, text/javascript, */*; q=0.01',        'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',        'X-Requested-With': 'XMLHttpRequest',        'Connection': 'keep-alive',        'TE': 'Trailers',    }    hour = time.strftime('%H',time.localtime(time.time())) # 當前小時    params = (        ('districtId', disID),        ('dir', '0'),        ('timeIndex', hour),    )    res = requests.get(url, headers=headers, params=params)    data = res.json()    return data

返回的資料為JSON格式,為一個列表,包含5個子列表,每個列表分別表示20分鐘、30分鐘、45分鐘、60分鐘、90分鐘的資料。 本以為到這裡就大功告成了,然而我們發現districtId為類似“B0FFFDS1JU”的字串編碼,不便於直接利用,因此需要找到它的來源。

2. 城市區域資料

同樣是透過F12抓包分析,可以找到一個請求,它可以返回每個城市對應的區域及相關資訊(包括了我們苦苦尋找的districtId)。那麼,便可以定義相應的函式:

def get_id(cityID):    '''    獲得城市區域ID    '''    url = 'https://report.amap.com/ajax/life/districts.do'    headers = {        'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0',        'Accept': 'application/json, text/javascript, */*; q=0.01',        'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',        'X-Requested-With': 'XMLHttpRequest',        'Connection': 'keep-alive',        'Referer': 'https://report.amap.com/life.do?city=420100',        'TE': 'Trailers',    }    params = (        ('cityCode', cityID),    )    res = requests.get(url, headers=headers, params=params)    data =res.json()    return data

透過傳入城市ID,便可得到其下區域的相關資訊:

如出一轍,傳入的引數為城市ID,這並不直觀,我們無法很快知道每個城市對應的ID是什麼。 正所謂:“探索尚未結束,同志仍需努力…”

3. 城市資料

如法炮製,我們找到了獲取城市資料的介面,並定義如下函式:

def get_city():    '''    獲取城市資訊(城市名、城市ID等)    '''    url = 'https://report.amap.com/ajax/getCityInfo.do'    headers = {        'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0',        'Accept': 'application/json, text/javascript, */*; q=0.01',        'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',        'X-Requested-With': 'XMLHttpRequest',        'Connection': 'keep-alive',    }    res = requests.get(url, headers=headers)    data = res.json()    return data

其結果如是:

4. 完整程式碼

為了更加方便地獲取資料,將以上函式整合在一起,完整的程式碼如下:

# -*- coding: utf-8 -*-"""Created on Mon Dec 21 15:14:42 2020@author: kimol_love"""import osimport timeimport jsonimport requestsdef get_city():    '''    獲取城市資訊(城市名、城市ID等)    '''    url = 'https://report.amap.com/ajax/getCityInfo.do'    headers = {        'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0',        'Accept': 'application/json, text/javascript, */*; q=0.01',        'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',        'X-Requested-With': 'XMLHttpRequest',        'Connection': 'keep-alive',    }    res = requests.get(url, headers=headers)    data = res.json()    return datadef get_id(cityID):    '''    獲得城市區域ID    '''    url = 'https://report.amap.com/ajax/life/districts.do'    headers = {        'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0',        'Accept': 'application/json, text/javascript, */*; q=0.01',        'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',        'X-Requested-With': 'XMLHttpRequest',        'Connection': 'keep-alive',        'Referer': 'https://report.amap.com/life.do?city=420100',        'TE': 'Trailers',    }    params = (        ('cityCode', cityID),    )    res = requests.get(url, headers=headers, params=params)    data =res.json()    return data    def get_data(disID):    '''    獲得交通生活圈資料    '''    url = 'https://report.amap.com/ajax/life/circle.do'    headers = {        'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0',        'Accept': 'application/json, text/javascript, */*; q=0.01',        'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',        'X-Requested-With': 'XMLHttpRequest',        'Connection': 'keep-alive',        'TE': 'Trailers',    }    hour = time.strftime('%H',time.localtime(time.time())) # 當前小時    params = (        ('districtId', disID),        ('dir', '0'),        ('timeIndex', hour),    )    res = requests.get(url, headers=headers, params=params)    data = res.json()    return dataif __name__ == '__main__':    # 獲取城市資訊    cityInfo = get_city()        # 輸入城市及片區    while True:        cityName = input('請輸入城市:')        flag = 0        for city in cityInfo:            if cityName == city['name']:                cityID = city['code']                disIDs = get_id(cityID)                if len(disIDs) == 0:                    flag = 1                else:                    flag = 2                break        if flag == 0: # 如果沒有該城市            print('未找到相關城市!')        elif flag == 1: # 如果該城市沒有資料            print('該城市無資料!:')        elif flag == 2:             break    print('-'*20)    print(('0==>所有').ljust(10))    for i in range(len(disIDs)):        print(('%d==>%s'%(i+1, disIDs[i]['name'])).ljust(10))    print('-'*20)    while True:        index = int(input('請選擇:'))        if index not in range(len(disIDs)+1):            print('輸入錯誤!:')        else:            break        # 下載資料    if not os.path.exists('./data'):        os.mkdir('./data')    if index == 0: # 全部下載        if not os.path.exists('./data/%s'%cityName):            os.mkdir('./data/%s'%cityName)        for i in range(len(disIDs)):            disID = disIDs[i]['id']            data = get_data(disID)            data.append(disIDs[i]['center']) # 加入中心點            data = json.dumps(data)            with open('./data/%s/%s.json'%(cityName,disIDs[i]['name']), 'w') as f:                f.write(data)                print('"%s"獲取成功!'%disIDs[i]['name'])    else:        disID = disIDs[index-1]['id']        data = get_data(disID)        data.append(disIDs[index-1]['center']) # 加入中心點        data = json.dumps(data)        with open('./data/%s.json'%disIDs[i]['name'], 'w') as f:            f.write(data)            print('"%s"獲取成功!'%disIDs[i]['name'])

注:為了便於後續地分析,我們將資料append了一個列表(區域的中心位置),因此data一共包含6個列表:5類資料+中心點位置。

俗話說得好,好用不好用,拉出來run一run:

電閃雷鳴之間,只見所有的資料默默地躺入了我溫暖的懷抱~ 至此,資料獲取的探索便可暫告於段落。

二、30分鐘交通生活圈1. 資料分析

有了資料,透過分析我們便可知道30分鐘自己能“走”多遠了。這裡我們用到了Python中的folium庫,它是一個互動式地相簿,允許我們呼叫地圖介面進行視覺化分析。其安裝方法如下:

pip install folium

首先,定義讀取資料的函式:

def read_data(path, Type=30):    '''    讀取交通生活圈資料(有20分鐘、30分鐘、45分鐘、60分鐘、90分鐘)    '''    typeMap = {20:0,               30:1,               45:2,               60:3,               90:4}    with open(path, 'r') as f:        data = f.read()    data = json.loads(data)    center = data[-1]    data = data[typeMap[Type]]    return (center, data)

讀取資料(以成都的牛王廟為例):

center, data = read_data('./data/成都/牛王廟.json')data.append(data[0])for i in range(len(data)): # 交換經緯度,很重要    data[i] = [data[i][1],data[i][0]]

data.append(data[0])是為了使資料形成一個閉環,這樣方便在地圖上表示出來。 定義地圖,並設定相關引數:

Map=folium.Map(location=[center[1],center[0]],        zoom_start=11,        tiles='http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}',        attr='default'    )

在地圖上標出起始點:

folium.Marker([center[1],center[0]],          popup=folium.Popup('牛王廟',max_width=1000),          tooltip='出發點'         ).add_to(Map)

在地圖上畫出30分鐘交通生活的區域:

folium.Polygon(data,               color='#7C9F59',               fill=True).add_to(Map)

將地圖儲存到本地:

Map.save('30分鐘交通生活圈.html')

開啟HTML之後,效果如下:

綠色區域意味著,在當前的交通情況下,我從牛王廟出發,我可以到達的範圍,即30分鐘我能“走”多遠~

2. 完整程式碼

這一部分的完整程式碼如下:

# -*- coding: utf-8 -*-"""Created on Mon Dec 21 18:58:34 2020@author: kimol_love"""import jsonimport foliumdef read_data(path, Type=30):    '''    讀取交通生活圈資料(有20分鐘、30分鐘、45分鐘、60分鐘、90分鐘)    '''    typeMap = {20:0,               30:1,               45:2,               60:3,               90:4}    with open(path, 'r') as f:        data = f.read()    data = json.loads(data)    center = data[-1]    data = data[typeMap[Type]]    return (center, data)if __name__ == '__main__':    center, data = read_data('./data/成都/牛王廟.json')    data.append(data[0])    for i in range(len(data)): # 交換經緯度,很重要        data[i] = [data[i][1],data[i][0]]    Map=folium.Map(location=[center[1],center[0]],            zoom_start=11,            tiles='http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}',            attr='default'        )    folium.Marker([center[1],center[0]],              popup=folium.Popup('牛王廟',max_width=1000),              tooltip='出發點'             ).add_to(Map)    folium.Polygon(data,                   color='#7C9F59',                   fill=True).add_to(Map)    Map.save('30分鐘交通生活圈.html')
寫在最後

至此,我們大致知道了30分鐘自己能“走”多遠了~

這裡主要是從交通通行情況的角度出發,如果非得說坐飛機、坐火箭、坐大炮啥的。別問我,問了我也不知道(手動捂臉)~

其實,這個資料還可以嘗試從更多地角度分析,比如可以計算出30分鐘最大抵達半徑,並進一步比較不同城市的大小等等。如果有感興趣的小夥伴,可以試試哦。

我是kimol君,咋們下次再會~

原文地址:想知道自己30分鐘能“走”多遠嘛?_kimol君的部落格-CSDN部落格

9
最新評論
  • 3本作者大大最好的一本小說,劇情讓人拍手叫好,連看三遍也不膩
  • “命好不好,嘴上見分曉”,高僧:嘴不好的人,多半命不好