前言
该篇文章是关键词搜索法获取高德poi,但鉴于无法突破200条记录的上限,所以采用了本方法进行区/县循环检索。开始之前我们首先需要明白一些常识
- poi是兴趣点,它本身除了经纬度,还记录了一些信息,如名称、地址、联系方式、所属行政区
- 高德poi是指从高德地图上获取poi,所以我们借助的平台是高德地图
- 高德地图知道有很多人需要用到poi,因此它十分良心地推出了若干个接口(API),借助这些API我们就可以各取所需。
API的理解
我们把整个poi的获取理解成以下几个步骤:
(1)找“高德地图”这个人申请要数据
(2)高德地图他说你申请数据需要先填一下这张数据需求表
(3)你拿到这张表(API),开始填写表(API)里的信息,包括POI的类别,POI的区域,需要数据的格式
(4)高德地图看了你填写的需求表,就从它的数据库里找到并且交回给你
(5)你拿到数据之后,筛选出关心的信息,之后就找各种方式把数据保存起来,例如存成一份excel表,或者一份txt文件,抑或是csv表格等等
所以通俗地讲,API就是一份表,通过这个表可以让对方返回你需要的东西,只不过实际上,这个表是用链接的形式发给你,在链接里填入信息就相当于填表的行为了。
使用说明
了解了相关信息后我们就可以进行开发测试,首先我们需要进入控制台获取key,这个操作很简单,如果不放心可以搜索一下到处都是教程。
第一步,申请”Web服务API”密钥(Key);
第二步,拼接HTTP请求URL,第一步申请的Key需作为必填参数一同发送;
第三步,接收HTTP请求返回的数据(JSON格式),解析数据。
如无特殊声明,接口的输入参数和输出数据编码全部统一为UTF-8。
适用场景
然后呢,我们从适用场景那里得知,这个搜索poi有四种方法可以获取poi,分别是关键字搜索、周边搜索、多边形搜索和ID查询,我们这里使用最简单的关键字搜索。
在这里仅仅对一部分URL和请求参数作出截图展示并介绍,详情请看https://lbs.amap.com/api/webservice/guide/api/search,高德地图在接口的使用上给出了详细的解释
1.key,就是我们上面申请的密钥
2.keywords或者types,注意是两者至少填一个,我示例里选择的是types
3.city,这个如果不填的话默认是帮你搜索全国的,但我们一般都会指定一个区域
4.page,你可以想象成一页页的纸,高德地图默认每页20条信息,默认返回一页给你,也就是20条。那么为了获取全部的poi,我们需要高德地图返回尽可能多页给我们,直到搜不到poi为止,因此这个参数在控制循环的时候尤为重要
5.output,返回的数据格式类型,我们一般都返回JSON格式,方便我们处理
不难发现,这个API里面有一些参数是我们熟悉的,例如keywords、city、key,并且这些关键词都是通过“&”符号进行连接,因此我们只要能够替换掉它的这些信息,就可以完成API的构建啦。
例如我需要获取东莞市的,就把 city=beijing改成city = 宜春市需要获取加油站类型的poi,就把keywords换成types,然后types = 加油站即可。
实现思路
我们现在已经学会怎么通过修改链接里的关键词来构建我们所需的API,那么下一步其实只需要向高德地图发出申请即可
但仔细思考,我们可以把整个过程划分成以下三个部分:
- 发出一次申请,高德地图返回一页数据给我,我们可以将这一次的申请想象成举手向老师拿东西(但注意,老师不会一次性把所有东西都给你)
- 我们通过某个指标,保证区域内的poi都获取完,这个过程理解为如果老师没有把东西全都给我,那我就一直举手,直到给完为止。
- 获取完之后我们需要将数据返回到前端展示,因此这个过程需要我们想方设法地存成某种文件。通过上面过程的划分,我们可以抽象成三个函数,一个举手函数,一个反复举手函数,一个返回展示函数(因为不复杂合二为一)。
实现代码
/**
* 高德地图OPI搜索加油站信息返回页面展示
*
* @author zhuoooo
* @data 2023/7/17 15:47
*/
@Controller
@RequestMapping("/map")
public class MapPOIController {
@Autowired
private RestTemplate restTemplate;
private final String key = "a0a72610dfc8e6eb2910734c4c30e9f4";
private final String url = "https://restapi.amap.com/v3/place/text";
// private final String city = "宜春市";//查询宜春市返回的数据显示不完整
private final String keywords = "加油站";
/**
* MVC实现点位数据的获取和页面展示
* @param model model
* @return 页面名称
*/
@RequestMapping("/poi")
public String index(Model model) {
//得到总共多少条数据(简单方法直接带入391)
//分页进行请求api
JSONArray pois = null;
int size = 0;
//分区/县循环进行查询数据并保存
String cities[] = {"袁州区", "万载县", "铜鼓县", "宜丰县", "上高县", "靖安县", "奉新县", "高安市", "樟树市", "丰城市"};
List<MapInfo> mapInfos = new ArrayList<>();
//每个城市进行循环查找数据
for (int k = 0; k < 10; k++) {
//每个城市查找两页(每页50,没有超过100的县城)
for (int j = 1; j <= 2; j++) {
pois = getPois(j, cities[k]);
size += pois.length();
if (pois.length() != 0) {
System.out.println(cities[k]+"第" + j + "躺的数据:" + pois);
//定义list存储加油站名称和位置信息
for (int i = 0; i < pois.length(); i++) {
//获取每一条数据的名称和位置信息
JSONObject poiJson = pois.getJSONObject(i);
String location = poiJson.get("location").toString();
String[] split = location.split(",");
String longitude = split[0];
String latitude = split[1];
String name = poiJson.get("name").toString();
//定义mapInfo将数据添加进去
MapInfo mapInfo = new MapInfo();
mapInfo.setLocation(location);
mapInfo.setLongitude(longitude);
mapInfo.setLatitude(latitude);
mapInfo.setName(name);
mapInfos.add(mapInfo);
}
}
}
}
model.addAttribute("size", size);
model.addAttribute("mapInfos", mapInfos);
return "gaode_map";
}
/**
* 调用高德API获取加油站点位数据
* @param page 页码
* @param city 城市
* @return 返回API调用的点位数据
*/
private JSONArray getPois(int page, String city) {
//API请求获取加油站json数据
String api = url + "?key=" + this.key + "&keywords=" + this.keywords + "&offset=50&city=" + city + "&page=" + page;
ResponseEntity<String> responseEntity = restTemplate.exchange(api, HttpMethod.GET, null, String.class);
String body = responseEntity.getBody();
//将Json数据转换成Java对象
JSONObject jsonObject = new JSONObject(body);
//获取pois属性list对象
JSONArray pois = jsonObject.getJSONArray("pois");
return pois;
}
}