当前位置: 首页 > 科技观察

想知道你的城市有多少条道路?我用Python发现北京有15000条路!

时间:2023-03-20 22:43:29 科技观察

本文转载自微信公众号《你可以叫我蔡哥》,作者蔡哥。如需转载本文,请联系我,叫我菜哥公众号。大家好,我是蔡哥。最近被催更了,今天开始一个系列吧。关于城市道路,本文主要演示城市道路数据的获取。接下来,我们将在此基础上拓展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、获取行政区域边界数据,直接按照开发者文档中的案例演示编写代码:importrequestsimportpandasaspdimportosurl='https://restapi.amap.com/v3/config/district?'key='yourkey'#You可以在高德开放平台注册一个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['longitude'].max()latitude_min=df['longitude'].min()longitude_max=df['Latitude'].max()longitude_min=df['latitude'].min()最后得到矩形区域内四个点的经纬度如下:upperleftcorner:115.423411,41.060816右上角:117.514625,41.060816左下角:115.423411,39.442758右下角:117.514625,39.442758矩形区域在上图中,我们可以看到矩形区域的很多部分不属于北京,所以不属于北京后续采集道具数据时需要判断道具所在省份是否属于北京。3.行政区域划分块既然我们已经得到了北京所属矩形区域边界点的经纬度,那么直接对矩形区域进行网格化就可以了。处理过程比较简单,直接看代码:#绘制网格,这里按照20*20共400个网格defget_polygons(latitude_num,longitude_num):#latitude_num=20#longitude_num=20latitude_step=(latitude_max-latitude_min)/latitude_numlongitude_step=(longitude_max-longitude_min)/longitude_numpolygons=[]foriinrange(latitude_num):latitude_leftup=latitude_min+latitude_step*iltitude_rightdown=latitude_min+latitude_step*(i+1)forjinrange(longitude_num):longitude_leftup=longitude_max-longitude_step*jlong??itude_rightdown=longitude_max-longitude_step*(j+1)polygon=downf'{latitude_leftup},{longitude_rightup}{longitude_rightdown}'polygons.append(polygon)returnpolygons我们得到了用于区域搜索纬度的坐标如下:#polygons['115.423411,41.06151.72|1915.06151.76,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',...]Gridization4.ObtainingroaddataAtthispoint,weonly需要遍历所有的coo坐标对多边形,然后搜索符合北京要求的区域中的省份所有道路#获取指定区域指定页面的道路数据并保存到本地defget_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='北京路名data.csv'forpoiinpois:ifpoi['pname']=='北京':df=pd.DataFrame({'road_id':poi['id'],'road_name':poi['name'],'road_adname':poi['adname']},index=[0])ifos.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')returnpois#这里分成20*20共400个区域polygons=get_polygons(20,20)fori,polygoninenumerate(polygons):page=1whileTrue:pois=get_road(polygon,page)ifpois==[]:breakpage+=1print(f'\r正在爬行{roaddataofi+1}/400regions',end='')最终我们得到了北京市一共14994条道路,各区道路数量如下:区道路编号顺义区2164大兴区1826TongzhouDistrict1310ChaoyangDistrict1264HaidianDistrict1088FangshanDistrict912MiyunDistrict907XichengDistrict896DongchengDistrict818ChangpingDistrict801PingguDistrict770FengtaiDistrict673YanqingDistrict553MentougouDistrict378HuairouDistrict372ShijingshanDistrict262Total14994