查看原文
其他

想知道所在的城市有多少条道路?我用python发现北京一共有1.5万条道路!

才哥 可以叫我才哥 2022-07-01

关注可以叫我才哥,学习分享数据之美

我们的第90篇原创

作者:才哥


大家好,我是才哥。

最近被催更了,害~

今天我们开启一个系列吧,关于城市道路的,本篇主要演示获取城市道路数据,接下来我们会在此基础上拓展1-2篇好玩的案例,敬请期待!

好了,我们开始今天的案例介绍。

1. 需求分析

我们以北京为例,希望获取该城市全部道路名称信息,主要字段有道路id、道路名称及所在区,基于高德地图的api接口。

我们找到高德api文档:https://lbs.amap.com/api/webservice/guide/api/search#t8

在搜索POI部分发现了查询城市道路名称的关键字搜索接口如下,但是该接口最多只能返回1000个数据。很明显北京市不止1000条道路,那么如何获取全部道路呢?

关键字搜索

终于,我们发现多边形搜索的接口,它可以对指定的矩形区域内的道路进行搜索,这样我们就脑洞一个想法将北京市按照经纬度分割为若干小区域,如果搜索各个区域内的道路数据后汇总就可以了,为了尽可能不要有遗漏,我们可以将区域颗粒度划分的小一些。

多边形搜索

那么,新的问题也来了:如何进行经纬度区域划分呢?我们又找到了行政区域查询接口文档:https://lbs.amap.com/api/webservice/guide/api/district

该接口通过行政区名称关键字就可以返回该行政区域的边界经纬度,如果我们只需要取经纬度各自的最大最小值就可以得到北京市所在的矩形区域,接着对这个矩形区域进行细化即可。

行政区域查询

思路有了,我们就开始干活吧!

2. 获取行政区域边界数据

直接按照开发者文档的案例演示编写代码如下:

import requests
import pandas as pd
import os

url = 'https://restapi.amap.com/v3/config/district?'
key = '你的key' # 自己在高德开放平台注册一个即可
keywords = '北京' # 可以换成你所在的城市
params = {
    'key':key,
    'keywords':keywords,
    'subdistrict':0,
    'extensions':'all',        
    }

r = requests.get(url,params=params)
data = r.json()
polyline = data['districts'][0]['polyline']
polyline_list = polyline.split(';')
df = pd.DataFrame(polyline_list,columns=['经纬度'])
df[['经度','纬度']] = df['经纬度'].str.split(',',n=1,expand=True).astype(float)

# 获取区域边界经纬度
latitude_max = df['经度'].max()
latitude_min =  df['经度'].min()
longitude_max =  df['纬度'].max()
longitude_min =  df['纬度'].min()

最后,矩形区域的四个点的经纬度如下:

左上角:115.423411,41.060816
右上角:117.514625,41.060816
左下角:115.423411,39.442758
右下角:117.514625,39.442758

矩形区域

上图中我们可以看到矩形区域很多部分不属于北京,所以在后续的道具数据采集的时候需要进行判断道路归属省份是否为北京。

3. 将行政区域分块

既然我们得到了北京所属矩形区域的边界点经纬度,那么直接这个矩形区域进行网格化就行了,处理过程比较简单,直接看代码:

# 绘制网格,这里按照20*20共400个网格
def get_polygons(latitude_num,longitude_num):
#    latitude_num = 20
#    longitude_num = 20
    latitude_step = (latitude_max - latitude_min)/latitude_num
    longitude_step = (longitude_max - longitude_min)/longitude_num
    polygons = []
    for i in range(latitude_num):
        latitude_leftup = latitude_min + latitude_step * i
        latitude_rightdown = latitude_min + latitude_step * (i+1)
        for j in range(longitude_num):
            longitude_leftup = longitude_max - longitude_step * j
            longitude_rightdown = longitude_max - longitude_step * (j+1)        
            polygon = f'{latitude_leftup},{longitude_leftup}|{latitude_rightdown},{longitude_rightdown}'
            polygons.append(polygon)     
    
    return polygons

我们得到了用于区域搜索经纬度坐标对如下:

# polygons 
['115.423411,41.060816|115.5279717,40.979913100000005',
 '115.423411,40.979913100000005|115.5279717,40.8990102',
 '115.423411,40.8990102|115.5279717,40.8181073',
 '115.423411,40.8181073|115.5279717,40.7372044',
...
]
网格化

4. 获取道路数据

到这一步,我们只需要遍历全部的坐标对polygons,然后搜索该区域内满足归属省份为北京市的全部道路即可。

# 获取指定区域指定page的道路数据并存到本地
def get_road(polygon,page):
    url = 'https://restapi.amap.com/v3/place/polygon?'
    params = {
        'key':key,
        'polygon':polygon,
        'keywords':'道路名',
        'types':190301,
        'offset':20,
        'page':page,
        'extensions':'all',        
        }  
    r = requests.get(url,params=params)    
    data = r.json()      
    pois = data['pois']
    file_name = '北京道路名称数据.csv'
    for poi in pois:
        if poi['pname'] =='北京市':
            df = pd.DataFrame({
                'road_id' : poi['id'],
                'road_name' : poi['name'],
                'road_adname' : poi['adname']
            },index=[0])
            if os.path.exists(file_name):
                df.to_csv(file_name, mode='a', header=False,
                  index=None, encoding='utf_8_sig')
            else:
                df.to_csv(file_name, index=None, encoding='utf_8_sig')

    return pois 
# 这里分为20*20共400个区域
polygons = get_polygons(20,20)   
for i,polygon in enumerate(polygons):
    page = 1
    while True:
        pois = get_road(polygon, page)
        if pois == []:
            break
        page += 1
    print(f'\r正在爬取第{i+1}/400个区域的道路数据',end='')

最终,我们得到了北京一共有14994条道路,其中各区道路数分别如下:

道路数
顺义区2164
大兴区1826
通州区1310
朝阳区1264
海淀区1088
房山区912
密云区907
西城区896
东城区818
昌平区801
平谷区770
丰台区673
延庆区553
门头沟区378
怀柔区372
石景山区262
总计14994

以上就是本次全部内容,感兴趣的同学公众号回复955可以获得源码。

后续我们结合道具数据试试一些好玩的探索吧,或者你有什么想法可以留言交流哦!

-->推荐阅读<--

用python绘制北京近一年来空气质量热力图,看看北京的沙尘暴真的多吗?

2021-03-16

Python爬取贝壳找房8万+二手房源,看看普通人在北京买房是有多难!

2020-12-30

Python爬取自如北京2.3万条租房信息,发现快租不起房子了

2020-12-16

Python探秘大众点评北京火锅店第①期:好吃的火锅在哪里?

2020-12-07

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存