Python获取高德POI(关键词搜索法)

本文介绍了如何利用高德地图API通过矩形搜索法获取超过900条的POI数据。通过构建申请、反复申请和保存数据的函数,实现了对指定区域和类型的POI数据的批量获取并存储为Excel文件。过程中涉及了坐标系转换,以解决高德坐标偏移问题。

高德POI的获取

改进代码

该篇文章是关键词搜索法获取高德poi,但鉴于无法突破900条记录的上限,因此重写了矩形搜索法的文章,具体可参考以下文章:

高德poi获取之矩形搜索法(冲出900条限制)

(建议没有python基础的朋友先阅读该篇再看矩形搜索法!)

前言

首先我们需要明白一些常识

  1. poi是兴趣点,它本身除了经纬度,还记录了一些信息,如名称、地址、联系方式、所属行政区
  2. 高德poi是指从高德地图上获取poi,所以我们借助的平台是高德地图
  3. 高德地图知道有很多人需要用到poi,因此它十分良心地推出了若干个接口(API),借助这些API我们就可以各取所需。
  4. 最容易被忽略的一点,通过高德地图获取得到的坐标会有偏移,具体详看3.2节,因此我们获取得到的坐标还需要经过坐标系转换才能得到正确的坐标,

API的理解
我们把整个poi的获取理解成以下几个步骤:
(1)找“高德地图”这个人申请要数据
(2)高德地图他说你申请数据需要先填一下这张数据需求表
(3)你拿到这张表(API),开始填写表(API)里的信息,包括POI的类别,POI的区域,需要数据的格式
(4)高德地图看了你填写的需求表,就从它的数据库里找到并且交回给你
(5)你拿到数据之后,筛选出关心的信息,之后就找各种方式把数据保存起来,例如存成一份excel表,或者一份txt文件,抑或是csv表格等等
所以通俗地讲,API就是一份表,通过这个表可以让对方返回你需要的东西,只不过实际上,这个表是用链接的形式发给你,在链接里填入信息就相当于填表的行为了

查看API接口

在高德开放平台上,我们获取poi所需的接口位于[开发支持]-[Web服务]-[Web服务API]下,点击即可进到主页。我们需要用到的接口如下图所示:
在这里插入图片描述
在这里插入图片描述

从图上可以知道,高德地图说想使用这个API,你必须有我家的密钥(key),因此我们首先需要去申请一下这个key。具体怎么申请可以参照以下这篇文章(https://zhuanlan.zhihu.com/p/96838566),接下来默认大家都有这个key了。

然后呢,我们从适用场景那里得知,这个搜索poi有四种方法可以获取poi,分别是关键字搜索、周边搜索、多边形搜索和ID查询,我们这里使用最简单的关键字搜索
在这里插入图片描述

在关键字搜索下面,我们可以看到有个请求参数的表格,这个请求参数其实就是API里需要我们填写的信息,我们看到那么多参数,其实不用慌,分清哪些是必填的,哪些是可填的,接下来就好办了。
在这里插入图片描述

在这里插入图片描述

从我框选的地方可以知道,其实必填的只有两三项。

1.key,就是我们上面申请的密钥
2.keywords或者types,注意是两者至少填一个,我示例里选择的是types
3.city,这个如果不填的话默认是帮你搜索全国的,但我们一般都会指定一个区域
4.page,你可以想象成一页页的纸,高德地图默认每页20条信息,默认返回一页给你,也就是20条。那么为了获取全部的poi,我们需要高德地图返回尽可能多页给我们,直到搜不到poi为止,因此这个参数在控制循环的时候尤为重要
5.output,返回的数据格式类型,我们一般都返回JSON格式,方便我们处理

接下来,我们查看一下返回的参数,这部分内容比较多,因此我录了个视频来讲解。

核心参数:

1. status
2. pois(核心参数:location、name等)

查看完返回结果参数之后,我们就已经明白了我们需要填写的信息和最后得到的信息有哪些,那么距离开始操作就只差最后一步了,就是拿表(API)填写
高德地图里给我们举了个栗子:
在这里插入图片描述

不难发现,这个API里面有一些参数是我们熟悉的,例如keywords、city、key,并且这些关键词都是通过“&”符号进行连接,因此我们只要能够替换掉它的这些信息,就可以完成API的构建啦。
例如我需要获取东莞市的,就把 city=beijing改成city = 东莞市需要获取公园类型的poi,就把keywords换成types,然后types = 公园即可。

实现思路

这是我的一些想法:

  1. 我们现在已经学会怎么通过修改链接里的关键词来构建我们所需的API,那么下一步其实只需要向高德地图发出申请即可

  2. 但仔细思考,我们可以把整个过程划分成以下三个部分:

    • 发出一次申请,高德地图返回一页数据给我,我们可以将这一次的申请想象成举手向老师拿东西(但注意,老师不会一次性把所有东西都给你)
    • 我们通过某个指标,保证区域内的poi都获取完,这个过程理解为如果老师没有把东西全都给我,那我就一直举手,直到给完为止。
    • 获取完之后我们需要将数据存到电脑上,因此这个过程需要我们想方设法地存成某种文件。
  3. 通过上面过程的划分,我们可以抽象成三个函数,一个举手函数,一个反复举手函数,一个保存结果函数。

  4. 虽然我在这次实验中需要获取高德地图poi,但如果下次我需要获取另外一个地方的其他类型poi,我能否用这次的方法来直接获取而不是重新写一次代码?

  5. 因此我想将上述的过程都封装成函数,下次再使用的时候只需要改改地区、poi类别即可完成所有工作。

实现过程

这里我们引入所需要的库

#库的说明
1.requests --爬虫常用库
2.json  --该库能够帮我们处理高德返回的JSON格式的数据
3.xlwt  --名字很奇怪,但它是xlsx、xls writer的意思,就是存储为excel表格库
4.Coordin_transformlat -- 这个是自己写的一个坐标转换的库,其目的是为了解决开头说的坐标偏移的问题
5.urlib -- 主要使用该库里的quote函数,因为当我们向电脑输入汉字时,计算机其实并不认识汉字,因为它只认识0101这些二进制代码,那么quote函数就可以将汉字翻译成计算机能够懂的语言。

#引入所需的库
import requests
import json
from urllib.parse import quote
import xlwt
from Coordin_transformlat import gcj02towgs84

1.构建一个申请的函数(举手函数)

回想一下刚刚的api,申请必须填写的几个参数:key,city,types或keywords,同时,容易忽略的一个参数是page,在请求函数里page是个可选参数,表示当前页数,我们可以通过递增page的值来反复地提交申请,例如第一次先申请第一页,第二次申请第二页这样实现,所以这里至少需要四个参数

代码理解
url: 是一个链接,通过访问这个链接,我们可以获取得到所需的数据
User-Agent:用户代理头,因为我们编写的是爬虫程序,通过爬虫去获取数据,而网站其实是不太支持爬虫爬取数据,因为爬虫的访问次数太快太多了,后台容易崩溃。那怎么让对方认不出来这是个爬虫呢?
通过添加User-Agent来给爬虫戴上用户(指正常浏览网站的人)的面具,这样瞒过对方视线,一般设置在headers里。
在这里插入图片描述

request.get():我们通过get(url,header)来爬取数据
get()方法,只要你输入一个网址就可以模拟人浏览网站的行为,相当于访问url这个链接

def Get_poi(key,city,types,page):
    '''
    这是一个能够从高德地图获取poi数据的函数
    key:为用户申请的高德密钥
    city:目标城市
    types:POI数据的类型
    page:当前页数
    '''
    
    #设置header
    header = {
   
   'User-Agent': "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50"}
    
    #构建url
    #{}在链接里表示占位符,也就是占住位置先不填写,.format()里就是往刚刚占位符的地方填写变量,按照顺序一一对应,第一个{}里是key,第二个{}里是types
    url = 'https://restapi.amap.com/v3/place/text?key={}&types={}&city={}&page={}&output=josn'.format(key,types,quote(city),page)

    #用get函数请求数据
    r = requests.get(url,headers=header)
    #设置数据的编码为'utf-8'
    r.encoding = 'utf-8'
    #将请求得到的数据按照'utf-8'编码成字符串
    data = r.text
    return data

2.构建反复申请的函数(多次举手)

这里只需要重复调用上面构造好的申请函数,直到最后一页的数据条数(Count)为0
在这里插入图片描述

因此这里只要当前页数(page)的记录条数(count)不为0,就一直执行循环

def Get_times(key,city,types):
    '''
    这是一个控制申请次数的函数
    '''
    page = 1
    #创建一个poilist的空列表
    poilist = []
    #执行以下代码,直到count为0的时候跳出循环
    while True:
        #调用第一个函数来获取数据
        result = Get_poi(key,city,types,page)
        
        #json.loads可以对获取回来JSON格式的数据进行解码
        content = json.loads(result)

        #content的样子其实跟返回结果参数是一样的,可以想象成有很多个字段的excel表格,下面这个语句就是提取出pois那个字段
        pois = content['pois']
        
        #pois的信息写入空列表里,这里由于不知道返回的数据长什么样子,所以会难以理解些
        for i in range(len(pois)):
            poilist.append(pois[i])
        
        #递增page
        page = page + 1

        #判断当前页下的count是否等于0
        if content['count'] == '0':
            break
    #将写好poi信息的列表返回
    return poilist

content的样子:
在这里插入图片描述

这图里,我们可以看到有很多条数据,这些数据就是高德地图返回给我们的,但类似于info、suggestion这些字段我们是不关心的,我们只关心pois这个字段,所以我们用pois = content['pois']这行代码来提取出pois这个字段。
但如果观察得仔细,你会发现pois字段里面还有很多的信息,除了我们关心的location、name以外,还有id、parent、email等,所以第三步需要我们再一次筛选信息

3.构建保存函数

通过上述的函数,我们得到了只包含pois字段的列表,但这个pois字段里还有很多无关的信息,因此我们这里单独提取出经纬度(location)、名称(name)、地址(address)

(下面这段代码是直接搬了别人的过来,现成的就不用自己再写一遍了,意义不大)
借鉴博客:(https://blog.csdn.net/john_ashley/article/details/114196683)

def write_to_excel(poilist, city,types):
    
评论 65
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值