百度地图为web开发者提供了基于HTTP/HTTPS协议的丰富接口,其中包括地点检索服务,web开发者通过此接口可以检索区域内的POI数据。百度地图处于数据保护对接口做了限制,每次访问服务,最多只能检索到400条数据,这样开发者就无法轻易的扒光收录的POI数据。作者基于 Golang 编写程序,完整获取百度地图POI数据。
百度地图WEB服务API基于HTTP/HTTPS协议,用户按照API文档要求的格式发送HTTP请求来获取POI数据,请求获取的数据格式可以为xml或json。
地点检索接口提供了3种检索方式:行政区划区域检索,圆形区域检索,矩形区域检索。详见接口文档。web 开发者在不同的场景可以采用不同的检索方式。
我们的目的是完整的获取POI数据,针对这一使用场景,最先想到是按照行政区划区域检索,先建立区域字典,然后一个区域一个区域的去获取数据。但是,有些区域POI的密度很大,一个市可能有数千家餐馆,而每次检索最多检索到400条数据,显然无法完整的拿到数据。
为突破数据保护的限制,这里采用矩形检索的方式。首先把要抓取的区域放到两经线和两纬线之间,构成一个大矩形(把地球看成方的),然后从大矩形的角落开始,逐个检索一个个小矩形,同时根据上一个小矩形的POI数量动态调整小矩形的面积。当所有小矩形组合覆盖完成大矩形之后,即可认为数据抓取完整。
OK,动手写代码!
需要考虑如下问题:
- 如何设置小矩形的初始面积?如何动态调整小矩形的面积?
- 地图API每日调用次数有限制, 超出限制之后如何继续上次的抓取?
提出这些问题之后,程序的大致结构有了,首先加载抓取状态数据,判断用户上次是否抓取完整,如果已经抓取完整,则让用户输入新的大矩形参数(两个经度,两个纬度);否则让用户决定是否继续抓取。
那么,状态数据应该包含哪些?该怎么存储状态数据呢?显然这么小的一个程序不需要用到数据库,存到文件中即可,而Golang处理JSON格式的数据很方便,所以状态数据可以以JSON格式存到文件中。存储的内容应该包含大矩形信息,小矩形信息,当前POI类别信息(POI文档),小矩形区域最近一次抓取的页号(每页最多20条),API调用信息。于是状态格式可以设计为:
{ "upperLatitude": 40.15, "lowerLatitude": 38.33, "leftLongitude": 116.42, "rightLongitude": 118.04, "apiAvailableTimes": 2000, "lastUseDate": "20181219", "apiKey": "申请的API Key", "lastLongitudePosition": 118.98, "lastLatitudePosition": 40.109, "lastCategoryIndex": 0, "lastLongitudeLength": 1.28, "lastLatitudeLength": 0.001, "lastPageIndex": -1 }