今天看啥  ›  专栏  ›  不正经的kimol君

想知道自己30分钟能“走”多远嘛?

不正经的kimol君  · CSDN  ·  · 2020-12-22 10:15

文章预览

前言

昨天在网上瞎逛的时候,看到了一个概念—— 交通生活圈 ,经过一番查阅后,约模知道了它的意思:在现有交通状况下,在一定的时间内乘坐现有交通工具你能抵达的范围(ps.通常是指驾车)。
简单来说,就是:“ 30分钟内你能走多远?
正好某德地图上也有类似的数据,效果如下:
在这里插入图片描述
它包含了20分钟、30分钟、45分钟、60分钟、90分钟这5类数据,它范围即对应的交通生活圈。感觉很厉害的鸭子~

于是,我决定自己探索一番…

一、获取数据

1. 交通生活圈数据

打开浏览器的F12调试工具,监听网络请求:
在这里插入图片描述
其接口地址为:

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

有3个参数,对应的说明如下:

参数 说明
districtId 表示区域的ID
dir 0表示出发地,1表示目的地
timeIndex 表示数据的时间

那么,可以定义获取数据的函数:

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

返回的数据为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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

通过传入城市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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

其结果如是:
在这里插入图片描述

4. 完整代码

为了更加方便地获取数据,将以上函数整合在一起,完整的代码如下:

# -*- coding: utf-8 -*-
"""
Created on Mon Dec 21 15:14:42 2020

@author: kimol_love
"""
import os
import time
import json
import requests

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

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
    
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

if __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']) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128

注: 为了便于后续地分析,我们将数据append了一个列表(区域的中心位置),因此data一共包含6个列表:5类数据+中心点位置。

俗话说得好,好用不好用,拉出来run一run:
在这里插入图片描述
电闪雷鸣之间,只见所有的数据默默地躺入了我温暖的怀抱~
至此,数据获取的探索便可暂告于段落。

二、30分钟交通生活圈

1. 数据分析

有了数据,通过分析我们便可知道30分钟自己能“走”多远了。这里我们用到了Python中的 folium库 ,它是一个交互式地图库,允许我们调用地图接口进行可视化分析。其安装方法如下:

pip install folium
  • 1
  • 1

首先,定义读取数据的函数:

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

读取数据(以成都的牛王庙为例):

center, data = read_data('./data/成都/牛王庙.json')
data.append(data[0])
for i in range(len(data)): # 交换经纬度,很重要
    data[i] = [data[i][1],data[i][0]]
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

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'
    )
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

在地图上标出起始点:

folium.Marker([center[1],center[0]],
          popup=folium.Popup('牛王庙',max_width=1000),
          tooltip='出发点'
         ).add_to(Map)
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

在地图上画出30分钟交通生活的区域:

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

将地图保存到本地:

Map.save('30分钟交通生活圈.html')
  • 1
  • 1

打开HTML之后,效果如下:
在这里插入图片描述
绿色区域 意味着,在当前的交通情况下,我从牛王庙出发,我可以到达的范围,即30分钟我能“走”多远~

2. 完整代码

这一部分的完整代码如下:

# -*- coding: utf-8 -*-
"""
Created on Mon Dec 21 18:58:34 2020

@author: kimol_love
"""
import json
import 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)

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')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

写在最后

至此,我们大致知道了30分钟自己能“走”多远了~

这里主要是从交通通行情况的角度出发,如果非得说坐飞机、坐火箭、坐大炮啥的。别问我,问了我也不知道(手动捂脸)~

其实,这个数据还可以尝试从更多地角度分析,比如可以计算出30分钟最大抵达半径,并进一步比较不同城市的大小等等。如果有感兴趣的小伙伴,可以试试哦。

我是kimol君,咋们下次再会~
在这里插入图片描述
创作不易,大侠请留步… 动起可爱的双手,来个赞再走呗 (๑◕ܫ←๑)

………………………………

原文地址:访问原文地址
快照地址: 访问文章快照
总结与预览地址:访问总结与预览