Python突破高德API限制完全爬取POI兴趣点数据 - Go语言中文社区

Python突破高德API限制完全爬取POI兴趣点数据


一、背景

        爬取POI数据,基本上是个老生常谈的话题了,现在市面上随处可见各路大神制作的获取POI数据的工具,但是当我将从高德地图中实际获取的POI数据与工具爬取的POI数据进行对比之后发现,市面上流行的工具并不能爬取所有的POI数据,获取的POI数据的数量往往与实际的POI数量相差甚远。

        博主闲来无事,尝试对青岛市带有“厕所”关键字的POI进行实验检索,注意到若在高德地图网页版的该市区域中搜索”厕所“二字,能够得出900条结果(高德对所有产品的POI检索做出了20X45条限制),而使用各种POI获取工具进行获取,仅能得到700余条、400余条、甚至200余条数据,甚坑,工具获取的数据数量甚至要比官方做出限制之后的POI数据数量还少!

二、流行工具解析

        现在市面上流行的POI工具的获取形式大概分为两种:

        (1)通过设定“城市名称”和“关键字”进行检索,例如输入”青岛“、”厕所“进行检索: 

            

          这样的方式获取POI的效果最差,首先会被官方限制900条上限,其次由于区域过大,很容易造成数据搜索不全,该工具在帮助中也说明了不建议采用这种方式。

      (2)通过设定多边形范围和关键字进行检索,例如设定青岛市区域的“多边形范围“、”厕所“进行检索:

           

       这种方式是该工具推荐的方式,能够获取数量较多的POI数据,但是经过检索实验发现,获取的POI数量仍然与实际相差较远,甚至连官方的900条限制都达不到。

       经过实验发现,按”城市名称“的检索方式效率最高且数据丢失相较不是很严重,多边形检索的方式虽能获取较多数据,但是数据丢失情况最为严重,特别是多边形的边缘部分。当然也有可能是分块不够小超过了官方规定。

三、解决思路:

        经过思考,有以下解决思路:

       (1)对多边形的检索方式进行改进,进行网格切分,博主的一篇博文:Python突破高德API限制爬取交通态势数据+GIS可视化(超详细)就是采用了此种方式,原理如下图。

              

    (2)对城市名称的检索方式进行改进,通过查看城市编码表,划分下级行政区进行分区检索,如下图。若要检索北京市的POI,可以通过划分下级行政区,分别检索东城区、西城区、朝阳区等等的POI,以获得较多数量的POI数据。注意若是填写汉字区划如”东城区“可能会出现问题,最保险的是填写”adcode“(即你身份证的前6位数字,代表了你的出生地)。

              

        经过实验发现,划分网格的方式对于突破POI限制并无太大作用,数据丢失简直严重到家了,注意到高德似乎有意限制了多边形边界区域的数据获取。划分行政区的方法是不错的选择,如果网友有更好的突破方法欢迎交流。

四、编写代码:

1、首先查阅高德城市编码表(下载地址:http://a.amap.com/lbs/static/file/AMap_adcode_citycode.xlsx.zip

2、找到你想要下载POI的城市,如青岛:

            

      对于”XX市市辖区“行可直接忽略,经实验使用该行进行检索会出现错误。

3、将该市的所有下级区的adcode保存,等待使用。

4、编写代码:

import requests
import pandas as pd
import json
import time
import math

#各下级行政区的代码,若是嫌逐个复制麻烦可以通过读取文件的方式实现,此处不进行讲解
arr=['370202','370203','370211','370212','370213','370214','370215','370281','370283','370285']
#API的URL,在这里进行了结构化处理
url1="https://restapi.amap.com/v3/place/text?keywords={关键词}&city="
url2="&output=JSON&offset=20&key={申请的KEY}&extensions=all&page="

#用于储存数据
x=[]
#用于计数
num=0

#循环各下级行政区进行POI检索
for i in range(0,len(arr)):
        #当前行政区
        city=arr[i]
        #因为官方对API检索进行了45页限制,所以只要检索到45页即可
        for page in range(1,46):
            #若该下级行政区的POI数量达到了限制,则警告使用者,之后考虑进行POI类型切分
            if page==45:
                print("警告!!POI检索可能受到限制!!")
            #构造URL
            thisUrl=url1+city+url2+str(page)
            #获取POI数据
            data=requests.get(thisUrl)
            #转为JSON格式
            s=data.json()
            #解析JSON
            aa=s["pois"]
            #若解析的JSON为空,即当前行政区的数据不够45页(即没有达到限制),返回
            if len(aa)==0:
                break
            #对每条POI进行存储
            for k in range(0,len(aa)):
                    s1=aa[k]["name"]
                    s2=aa[k]["type"]
                    s3=aa[k]["address"]
                    s4=aa[k]["adname"]
                    s5=aa[k]["location"].split(",")                    
                    x.append([s1,s2,s3,s4,float(s5[0]),float(s5[1])])
                    num+=1
                    print("爬取了 "+str(num)+" 条数据")

#将数据结构化存储至规定目录的CSV文件中
c = pd.DataFrame(x)
c.to_csv('E:/toilet.csv',encoding='utf-8-sig')

       注意:爬取的POI数据是GCJ-02坐标,不要忘了进行纠偏,在这里不进行讲解。

       程序运行完毕即可在相关目录中找到爬取的POI数据,最终获得了2000余条数据,之后可使用GIS软件进行可视化。

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/Smart3S/article/details/88045365
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-06-26 17:14:14
  • 阅读 ( 712 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢