绘制北京市蜜雪冰城门店地图

x33g5p2x  于2022-06-20 转载在 其他  
字(7.1k)|赞(0)|评价(0)|浏览(1011)

总共分3步:
    第一步,通过腾讯地图API收集门店地理位置数据;
    第二步,将地理位置数据导入Elasticsearch;
    第三步,使用Kibana绘制门店地图。
    下面详细展开。

1. 收集门店地理位置数据

按照 WebService API 文档的步骤申请密钥,文档网址为: https://lbs.qq.com/service/webService/webServiceGuide/webServiceOverview 。

密钥申请下来:

可以将演示的密钥换成自己的Key进行测试:

https://apis.map.qq.com/ws/place/v1/search?keyword=酒店&boundary=nearby(39.908491,116.374328,1000)&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77

接下来,本人准备使用 “城市/区域搜索” 这个接口,网址:https://lbs.qq.com/service/webService/webServiceGuide/webServiceSearch 。

学习了一下请求参数,其中必填参数有3个,分别是 keyword,boundary 和 key 。另外还用到了参数 page_size 和 page_index。因为每次查询最多返回 200 条数据,在无法预估结果的情况下,本人决定逐个行政区进行查询,boundary 参数的 city_name 将使用 adcode,即行政区划代码。北京市代码如下:

这里,本人编写了一个脚本,调用 API 接口,将数据存储进 mxbc.json 文件

import requests     #调用接口
import time         #防止并发限制
import tqdm         #查看进度

#keyword: 搜索关键字,长度最大96个字节,注:keyword仅支持检索一个。
#city_name: 检索城市名称,支持adcode(行政区划代码,可精确到区县级)
keyword = '蜜雪冰城'
city_name = ['110101','110102','110105','110106','110107','110108','110109',
'110111','110112','110113','110114','110115','110116','110117','110118','110119']

#请求函数
def base_request(city, page = 1): 
    url = "https://apis.map.qq.com/ws/place/v1/search?"     #接口地址
    params = {'keyword':keyword,                            #查找的关键字
              'boundary':'region(' + city + ',2)',          #范围
              'key':'xxxxx',                                #你的key
              'page_index':page,                            #显示几页
              'page_size':20}                               #每页条目数,最大限制为20条 
    response = requests.get(url,params=params)              #调用接口
    answer = response.json()                                #接收返回的数据
    
    print("%s 有 %d 家门店" %(city,answer["count"]))
    f = open("./mxbc.json", "a+")                           #将返回结果逐行写入文件
    for line_number in range(0,len(answer["data"])):
        f.write(str(answer["data"][line_number]) + "\n")
    f.close()
    time.sleep(1)
    return answer["count"] // -20 * -1                      #每页条目数为20时,返回总页数

for city in tqdm.tqdm(city_name):                           #顺序查询各区情况,tqdm显示进度
    page_index = base_request(city)                         #返回门店数量
    if page_index > 1:                                      #返回结果每页最多20,结果大于1页,逐页处理
        for page in range(2, page_index + 1):
            base_request(city, page) 
    else:
        continue

运行效果如下:

得到的数据如下:

{'id': '17153800364953537565', 'title': '蜜雪冰城(南锣鼓巷店)', 'address': '北京市东城区鼓楼东大街164号(工商银行与穿行体育中间)', 'tel': '13520051612', 'category': '美食:冷饮店', 'type': 0, 'location': {'lat': 39.940685, 'lng': 116.400879}, 'ad_info': {'adcode': 110101, 'province': '北京市', 'city': '北京市', 'district': '东城区'}}
{'id': '7100735642175914831', 'title': '蜜雪冰城(国瑞购物中心店)', 'address': '北京市东城区崇文门外大街18号(近西花市大街)国瑞购物中心G', 'tel': '18226293405', 'category': '美食:冷饮店', 'type': 0, 'location': {'lat': 39.898211, 'lng': 116.41924}, 'ad_info': {'adcode': 110101, 'province': '北京市', 'city': '北京市', 'district': '东城区'}}
{'id': '17783258983880652103', 'title': '蜜雪冰城(簋街店)', 'address': '北京市东城区东直门内大街178号', 'tel': '17330593555', 'category': '美食:冷饮店', 'type': 0, 'location': {'lat': 39.94083, 'lng': 116.423554}, 'ad_info': {'adcode': 110101, 'province': '北京市', 'city': '北京市', 'district': '东城区'}}
{'id': '4146011748979863497', 'title': '蜜雪冰城(银河Soho商场店)', 'address': '北京市东城区南竹杆胡同2号银河Soho商场B1', 'tel': '17527357702', 'category': '美食:冷饮店', 'type': 0, 'location': {'lat': 39.921109, 'lng': 116.433767}, 'ad_info': {'adcode': 110101, 'province': '北京市', 'city': '北京市', 'district': '东城区'}}
... ...
2. 将数据导入 Elasticsearch

环境:

  • Elasticsearch 7.17.0
  • Kibana 7.17.0
2.1 创建索引

可以使用两种方法创建索引。
    第一种方法,使用 dev_tools 创建。因为本例中 Elasticsearch 是单机运行,这里使用以下命令:

PUT /mxbc
{
  "settings":{
    "number_of_shards" :   1,
    "number_of_replicas" : 0
  },
  "mappings": {
    "properties": {
                "id":{"type":"text"},
                "title":{"type":"keyword"},
                "address":{"type":"text"},
                "tel":{"type":"text"},
                "category":{"type":"text"},
                "type":{"type":"integer"},
				"location" : {"type" : "geo_point"},
                "adcode":{"type":"keyword"},
                "province":{"type":"text"},
                "city":{"type":"text"},
                "district":{"type":"keyword"}
    }
  }
}

创建成功:

第二种方法,使用 curl 命令直接创建。使用以下命令:

curl --user 'username':'password' -X PUT "192.168.198.145:9200/mxbc2?pretty" -H 'Content-Type: application/json' -d'
{
  "settings":{
    "number_of_shards" :   1,
    "number_of_replicas" : 0
  },
  "mappings": {
    "properties": {
                "id":{"type":"text"},
                "title":{"type":"keyword"},
                "address":{"type":"text"},
                "tel":{"type":"text"},
                "category":{"type":"text"},
                "type":{"type":"integer"},
				"location" : {"type" : "geo_point"},
                "adcode":{"type":"keyword"},
                "province":{"type":"text"},
                "city":{"type":"text"},
                "district":{"type":"keyword"}
    }
  }
}
'

创建过程如下:

两种方法最终都可以创建成功,效果如下:

2.2 整理格式

为了满足 Bulk API 格式,便于批量导入,需要在每行数据前面添加 index 信息。python脚本处理一下:

f = open("./bulk.txt", "a+")
for line in open("mxbc.json"): 
    index = "{\"index\":{\"_index\":\"mxbc\"}}"
    index = index + '\n' + line
    f.write(index)
f.close()

生成文档 bulk.txt,内容为:

# head bulk.txt
{"index":{"_index":"mxbc"}}
{'id': '17153800364953537565', 'title': '蜜雪冰城(南锣鼓巷店)', 'address': '北京市东城区鼓楼东大街164号(工商银行与穿行体育中间)', 'tel': '13520051612', 'category': '美食:冷饮店', 'type': 0, 'location': {'lat': 39.940685, 'lng': 116.400879}, 'ad_info': {'adcode': 110101, 'province': '北京市', 'city': '北京市', 'district': '东城区'}}
{"index":{"_index":"mxbc"}}
{'id': '7100735642175914831', 'title': '蜜雪冰城(国瑞购物中心店)', 'address': '北京市东城区崇文门外大街18号(近西花市大街)国瑞购物中心G', 'tel': '18226293405', 'category': '美食:冷饮店', 'type': 0, 'location': {'lat': 39.898211, 'lng': 116.41924}, 'ad_info': {'adcode': 110101, 'province': '北京市', 'city': '北京市', 'district': '东城区'}}
{"index":{"_index":"mxbc"}}
{'id': '17783258983880652103', 'title': '蜜雪冰城(簋街店)', 'address': '北京市东城区东直门内大街178号', 'tel': '17330593555', 'category': '美食:冷饮店', 'type': 0, 'location': {'lat': 39.94083, 'lng': 116.423554}, 'ad_info': {'adcode': 110101, 'province': '北京市', 'city': '北京市', 'district': '东城区'}}
{"index":{"_index":"mxbc"}}
{'id': '4146011748979863497', 'title': '蜜雪冰城(银河Soho商场店)', 'address': '北京市东城区南竹杆胡同2号银河Soho商场B1', 'tel': '17527357702', 'category': '美食:冷饮店', 'type': 0, 'location': {'lat': 39.921109, 'lng': 116.433767}, 'ad_info': {'adcode': 110101, 'province': '北京市', 'city': '北京市', 'district': '东城区'}}
{"index":{"_index":"mxbc"}}
{'id': '7680346462735838662', 'title': '蜜雪冰城(东方广场店)', 'address': '北京市东城区长安街1号东方广场BB80号', 'tel': '13661055941', 'category': '美食:冷饮店', 'type': 0, 'location': {'lat': 39.909089, 'lng': 116.414132}, 'ad_info': {'adcode': 110101, 'province': '北京市', 'city': '北京市', 'district': '东城区'}}

不要忘记处理一下坐标,lng 需要变为 lon,同时单引号需要变换成双引号,否则后面无法导入:

sed -i s/lng/lon/g bulk.txt
sed -i s/\'/\"/g bulk.txt
2.3 导入数据

使用命令将 bulk.txt 内数据导入 Elasticsearch:

curl --user 'username':'password' -H 'Content-Type: application/x-ndjson' -XPOST '192.168.198.145:9200/mxbc/_bulk?pretty' --data-binary @bulk.txt

Kibana 创建 Index pattern 后,可以查询到这些数据,共 199 条。

3. 使用 Kibana 绘制门店地图
3.1 展示门店位置

点击 Maps - Add layer - Documents,按步骤设置,即可展示门店位置

Name 命名为“门店位置”,visibility(可见度)根据需要进行设置。Label 设置为 title,可展示门店名称:

3.2 聚合门店数量

点击 Add layer - Clusters and grids,按步骤设置,即可聚合门店数量

默认按照区域内数量进行聚合:

最后放一张俯视图结束:

相关文章