poi官方文档_空间分析:1-1.高德地图获取北京所有小区的POI

本文介绍如何利用高德地图开放平台的Web API服务,通过递归网格划分的方法在北京范围内搜索并获取住宅小区的POI数据。首先,确定北京地理范围,并将其划分为多个网格;随后,对每个网格调用API,如果返回结果超过预设阈值,则进一步细分网格,直至获取所有符合条件的小区数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们使用高德开放平台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=<用户的key>

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

把polyline:后面跟着那一串,复制保存在polyline.txt文件中,双引号不用留。

0cd2ae4a245a03448b58181c3aa3a99d.png

二.递归拆分网格

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

先看说明:

高德地图开放平台——开发指南——搜索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=<用户的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这个中类的码入参,但反正也不考虑别墅,就算了吧。)

3b09f42e85fe4fdbc5305c85b707d11d.png

4.offset,每页记录数据,offset=20。

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

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

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

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

e2c4e17b892bf62c35b1226ed4e715f0.png

我们继续看返回参数说明,count,搜索方案数目(最大值为1000)。

79ac9a5099678886250f359b99f55eb1.png

这说明啥?

按照官方文档,矩形搜索,最多返回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.将处理好的矩形写入文件备用。

结果如下图:

9150065eec005e11a530aead32c57012.png

代码如下,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 < maxcount:
            fnew.write(str(r[0])+','+str(r[1])+'|'+str(r[2])+','+str(r[3])+'t'+str(count)+'n')
        else:
            rectangles.extend(clipRectangle(r))
    fnew.close()

三.获取小区数据

一个很简单的脚本,获取所有小区的name、id、address、location,保存在xiaoqu.txt中。

import requests
from requests.adapters import HTTPAdapter
import math
s = requests.Session()
s.mount('http://', HTTPAdapter(max_retries=3))#设置重试次数为3次
s.mount('https://', HTTPAdapter(max_retries=3))
# 获取小区POI
# key,是高德地图的key
# r是矩形,minlng,minlat|maxlng,maxlat
# page是页码
def getPoi(key,r,page):
    url = 'https://restapi.amap.com/v3/place/polygon?types=120302&offset=20&page='+str(page)+'&extensions=all&output=json&polygon='
        + r + '&key=' + key
    print(url)
    result = []
    try:
        r = s.get(url, timeout=5)
        data = r.json()
        if 'status' in data:
            if data['status'] == '1':
                pois = data['pois']
                for p in pois:
                    result.append([str(p['id']),str(p['name']),str(p['location']),str(p['address'])])
    except BaseException as e:
        print(e)
    return result
if __name__ =='__main__':
    key = ''
    f = open(r'rectangles.txt','r',encoding='utf-8')
    fnew = open(r'xiaoqu.txt','a',encoding='utf-8')
    flines = f.readlines()
    f.close()
    for l in flines:
        llist = l.strip('n').split('t')
        r = llist[0]
        count = int(llist[1])
        if count < 1:
            continue
        # 整除,向上取整
        pagenum = math.ceil(count/20)
        for i in range(1,pagenum+1):
            result = getPoi(key,r,i)
            if len(result) > 0:
                for re in result:
                    print(re)
                    fnew.write('t'.join(re)+'n')
    fnew.close()

获取的所有小区数据如下:

15899a7b2e58c63299ccb3bc020f3c11.png

四、小结

以上代码,只要把key换一下,就能运行,把type换一下,就能获取其他类型的POI。

<think>好的,我现在需要帮助用户解决关于高德地图POI API的使用问题。用户已经提供了两个引用,其中引用[1]提到了如何在Android中实现POI搜索,包括申请API Key、添加依赖、权限配置以及示例代码。引用[2]则介绍了一个第三方库AMapPoi,可能对数据处理有帮助。 首先,用户的问题是关于POI API的使用教程、示例代码和文档。我需要先整理高德地图官方文档中的核心步骤,确保步骤正确,并且结合用户提供的引用内容。例如,申请API Key、配置项目、编写搜索代码这些步骤在引用[1]中已经提到,我需要进一步详细说明,并确保代码示例与用户提供的Python示例不同,因为高德地图通常使用Java或Kotlin。 接下来,用户可能需要了解如何解析POI数据,这时候可以推荐引用[2]中的AMapPoi库,作为辅助工具。同时,注意事项部分需要提醒用户关于网络权限、API Key配置以及合规使用数据的问题,这些都是开发中常见的坑。 然后,生成相关问题时要覆盖用户可能进一步关心的内容,比如参数调整、周边搜索数据解析优化、错误处理、性能优化以及第三方库的使用。这些问题需要自然衔接,帮助用户深入探索。 需要检查是否有遗漏的步骤,例如依赖库的添加是否正确,权限是否全面,以及示例代码是否有误。同时,确保所有技术细节符合高德地图最新的文档,因为API可能会有更新。如果用户提供的引用中有过时的信息,可能需要提示用户查阅最新文档,但根据现有引用内容,暂时按照提供的资料来回答。 最后,保持回答结构清晰,分步骤说明,代码部分用正确的格式标注,并正确引用来源。同时,语言要简洁明了,避免技术术语过多,方便用户理解。</think>### 高德地图 POI API 使用教程与示例 #### 一、核心步骤说明 1. **申请API Key** - 登录[高德开放平台](https://lbs.amap.com/),创建应用并绑定「Web服务API」和「Android平台」 - 在「应用管理」中获取`SHA1`指纹与包名,生成专属API Key[^1] 2. **Android项目配置** ```gradle // build.gradle 添加依赖 implementation 'com.amap.api:search:latest_version' implementation 'com.amap.api:location:latest_version' ``` ```xml <!-- AndroidManifest.xml 添加权限 --> <uses-permission android:name="android.permission.INTERNET"/> <meta-data android:name="com.amap.api.v2.apikey" android:value="YOUR_API_KEY"/> ``` 3. **POI搜索实现** ```java // MainActivity.java 核心代码 public class MainActivity extends AppCompatActivity { private PoiSearch.Query query; private PoiSearch poiSearch; void searchPOI(String keyword) { query = new PoiSearch.Query(keyword, "", "城市编码"); query.setPageSize(10); // 设置每页数量 poiSearch = new PoiSearch(this, query); poiSearch.setOnPoiSearchListener(new OnPoiSearchListener() { @Override public void onPoiSearched(PoiResult result, int rCode) { if (rCode == 1000) { ArrayList<PoiItem> items = result.getPois(); // 处理搜索结果 } } }); poiSearch.searchPOIAsyn(); } } ``` #### 二、数据解析建议 推荐使用开源库`AMapPoi`进行高级处理,支持地理编码与数据清洗: ```python # 通过AMapPoi库解析数据示例 from amappoi import AMapPoiClient client = AMapPoiClient(api_key='your_key') results = client.search(keywords='咖啡馆', city='北京') for poi in results: print(f"名称:{poi.name} 地址:{poi.address}") ``` 项目地址: [AMapPoi](https://gitcode.com/gh_mirrors/am/AMapPoi)[^2] #### 三、注意事项 1. 确保网络权限和定位权限已声明 2. API调用频率需遵守平台限制(默认3000次/日) 3. POI数据使用时需遵守《高德地图开放平台服务协议》
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值