高德地图获取城市所有小区的POI

您所在的位置:网站首页 搜索北京的地图 高德地图获取城市所有小区的POI

高德地图获取城市所有小区的POI

2023-11-19 21:24| 来源: 网络整理| 查看: 265

我们使用高德开放平台https://lbs.amap.com上的webapi服务,获取POI数据,严格说来不算爬虫,就是调数据接口获取数据而已。

步骤也很简单。

1.获取北京的范围。

2.将北京范围拆分成设定步长的网格,用每个网格矩形搜索小区数据,如果搜索到的数据量大于阈值,则将网格拆分成四个,如此递归,直到矩形搜索到的数据量小于阈值。

3.用2中获取的网格调用接口,获取小区数据,把所有网格的数据汇总到一起就可以了。

稍稍有点难度的,可能就是网格拆分的递归,但只要想明白了,就也很简单。

接下来,看实践。

一.获取北京范围

看说明:高德地图开放平台——开发指南——行政区划查询。

https://lbs.amap.com/api/webservice/guide/api/district

根据请求参数说明,拼接出如下一个url,就可以获取北京范围的数据了,当然,用户key自己申请一个。

https://restapi.amap.com/v3/config/district?keywords=北京&subdistrict=0&extensions=all&key=

polyline就是北京边界坐标点串,拷贝下来,留着备用。

把polyline:后面跟着那一串,复制保存在polyline.txt文件中,双引号不用留。 在这里插入图片描述

二.递归拆分网格

为了便于理解,我们把拆分网格和获取数据分开写。

先看说明:

高德地图开放平台——开发指南——搜索POI——多边形搜索:

https://lbs.amap.com/api/webservice/guide/api/search

多边形搜索的示例:

https://restapi.amap.com/v3/place/polygon?polygon=116.460988,40.006919|116.48231,40.007381|116.47516,39.99713|116.472596,39.985227|116.45669,39.984989|116.460988,40.006919&keywords=kfc&output=xml&key=

根据多边形搜索条目下的请求参数说明,可以知道,在url中,我们需要拼接几个参数,才能获取数据。

1.key,需要在高德地图开放平台上申请,既key=用户的key

2.polygon,图简单,我们使用矩形,传左下右上两个顶点坐标对,既polygon=minlng,minlat|maxlng,maxlat

3.types,查询的POI类型,这个查《POI分类编码》,能看到(大类)商务住宅——(中类)住宅区——(小类)住宅小区的NEW-TYPE是120302,中类住宅区的NEW-TYPE是120300,既types=12302。

(其实也可以用120300这个中类的码入参,但反正也不考虑别墅,就算了吧。) 在这里插入图片描述 4.offset,每页记录数据,offset=20。

5.page,当前页数,这个需要根据返回的POI总量算,从1开始。

6.extensions,返回结果控制,多多益善,extensions=all。

7.output,返回数据格式类型,output=json。

根据offset和page的说明,offset是强烈建议不超过25,若超过25可能造成访问报错,page是最大翻页数100,这表明,每次矩形搜索最多返回2500条记录。

**加粗样式 ** 我们继续看返回参数说明,count,搜索方案数目(最大值为1000)。 在这里插入图片描述 这说明啥?

按照官方文档,矩形搜索,最多返回1000条数据,为了获取足够的数据,我们只能把搜索的矩形不断细分变小。理论上,在同一个地方,范围越小,内含的数据就越少。

假设说,一个矩形覆盖整个北京,通过这个矩形调接口,返回count=1000,那我们就要把这个矩形拆分一下,横一刀,竖一刀,变成0、1、2、3四个小矩形,再通过这四个小矩形调接口,如果0返回的count小于1000,那它不用再拆分了,如果1返回的count=1000,那它需要继续拆分,如此递归下去,直到所有的矩形调接口,返回的count都小于1000。

虽然按官方说明,阈值选1000是正确的,但按照实践来看,这个阈值选800正好,因为我发现,挺大个矩形,返回的count是800多,拆成4个,每个小矩形也返回count是800多,这就有点不太合理了,实践出真知,那就用800做阈值吧。

总结一下:

1.先根据北京范围拆分基础的矩形网格。

2.根据这个基础的矩形网格,去调用高德多边形搜索服务,如果搜索出的小区小于800个,则保留矩形,否则拆分矩形,直到矩形搜索出的小区小于800个。

3.将处理好的矩形写入文件备用。

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

代码如下,Python3代码,需要的包是requests和shapely,其实基础的矩形网格拆分得足够小,就都不用递归了,如果想看看递归效果,可以把步长d设置得大一些。也可以把代码改一改,获取其他类型的POI等。

import requests from shapely.geometry import Polygon from shapely import wkt from requests.adapters import HTTPAdapter s = requests.Session() s.mount('http://', HTTPAdapter(max_retries=3))#设置重试次数为3次 s.mount('https://', HTTPAdapter(max_retries=3)) # 获取矩形搜索到poi的count数量 # key,是高德地图的key # r是矩形,[minlng,minlat,maxlng,maxlat] def countSearchPoi(key,r): minlng = r[0] minlat = r[1] maxlng = r[2] maxlat = r[3] url = 'https://restapi.amap.com/v3/place/polygon?types=120302&offset=20&page=1&extensions=all&output=json&polygon='\ + str(minlng) +',' + str(minlat) + '|' + str(maxlng) + ',' + str(maxlat) + '&key=' + key count = -1 print(url) try: r = s.get(url, timeout=5) data = r.json() if 'status' in data: if data['status'] == '1': count = int(data['count']) except BaseException as e: print(e) return count # 切分矩形,把大矩形分成四个小矩形 def clipRectangle(r): minlng = r[0] minlat = r[1] maxlng = r[2] maxlat = r[3] dx = 0.5*(maxlng-minlng) dy = 0.5*(maxlat-minlat) return [[minlng,minlat,minlng+dx,minlat+dy],[minlng+dx,minlat,maxlng,minlat+dy], [minlng+dx,minlat+dy,maxlng,maxlat],[minlng,minlat+dy,minlng+dx,maxlat]] # 按照步长,将面切分成矩形网格,把所有跟入参的面相交的矩形都返回 # polygon是多边形geometry,d是步长 def clipPolygon(polygon,d): bbox = polygon.bounds rectangles = [] lngnum = int((bbox[2]-bbox[0])/d)+1 latnum = int((bbox[3]-bbox[1])/d)+1 minlng = int(bbox[0]/d)*d minlat = int(bbox[1]/d)*d for i in range(0,lngnum+1): for j in range(0,latnum+1): rectangle = Polygon([(minlng+d*i,minlat+d*j),(minlng+d*i+d,minlat+d*j), (minlng+d*i+d,minlat+d*j+d),(minlng+d*i,minlat+d*j+d),(minlng+d*i,minlat+d*j)]) if polygon.intersects(rectangle): rectangles.append([minlng+d*i,minlat+d*j,minlng+d*i+d,minlat+d*j+d]) return rectangles if __name__ =='__main__': d = 0.05 maxcount = 800 key = '' # 将北京的范围坐标点串从txt文件中读出,构建成polygon fpolyline = open(r'polyline.txt','r',encoding='utf-8') polyline = fpolyline.readlines()[0].strip('\n') fpolyline.close() polygonstr = 'POLYGON(('+polyline.replace(',',' ').replace(';',',')+'))' polygon = wkt.loads(polygonstr) # 根据polygon和步长,构建矩形网格 rectangles = clipPolygon(polygon,d) fnew = open(r'rectangles.txt','a',encoding='utf-8') # 嵌入递归 for r in rectangles: # 如果矩形构建的polygon与北京范围polygon不相交,进入下一个 rp = Polygon([(r[0],r[1]),(r[2],r[1]),(r[2],r[3]),(r[0],r[3]),(r[0],r[1])]) if not polygon.intersects(rp): continue count = countSearchPoi(key,r) print(count) # 如果count小于阈值,将矩形和count写入文件,否则将矩形拆分,进行递归 if count


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3