我用Python发现北京共有1.5万条路

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

END -

本文为转载分享&推荐阅读,若侵权请联系后台删除
-------------------------------------
长按识别下方二维码,并关注公众号

1.回复“PY”领取1GB Python数据分析资料

2.回复“BG”领取3GB 名企数据分析报告
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值