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

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

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

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

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

密钥申请下来:

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

  1. 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 文件

  1. import requests #调用接口
  2. import time #防止并发限制
  3. import tqdm #查看进度
  4. #keyword: 搜索关键字,长度最大96个字节,注:keyword仅支持检索一个。
  5. #city_name: 检索城市名称,支持adcode(行政区划代码,可精确到区县级)
  6. keyword = '蜜雪冰城'
  7. city_name = ['110101','110102','110105','110106','110107','110108','110109',
  8. '110111','110112','110113','110114','110115','110116','110117','110118','110119']
  9. #请求函数
  10. def base_request(city, page = 1):
  11. url = "https://apis.map.qq.com/ws/place/v1/search?" #接口地址
  12. params = {'keyword':keyword, #查找的关键字
  13. 'boundary':'region(' + city + ',2)', #范围
  14. 'key':'xxxxx', #你的key
  15. 'page_index':page, #显示几页
  16. 'page_size':20} #每页条目数,最大限制为20条
  17. response = requests.get(url,params=params) #调用接口
  18. answer = response.json() #接收返回的数据
  19. print("%s 有 %d 家门店" %(city,answer["count"]))
  20. f = open("./mxbc.json", "a+") #将返回结果逐行写入文件
  21. for line_number in range(0,len(answer["data"])):
  22. f.write(str(answer["data"][line_number]) + "\n")
  23. f.close()
  24. time.sleep(1)
  25. return answer["count"] // -20 * -1 #每页条目数为20时,返回总页数
  26. for city in tqdm.tqdm(city_name): #顺序查询各区情况,tqdm显示进度
  27. page_index = base_request(city) #返回门店数量
  28. if page_index > 1: #返回结果每页最多20,结果大于1页,逐页处理
  29. for page in range(2, page_index + 1):
  30. base_request(city, page)
  31. else:
  32. continue

运行效果如下:

得到的数据如下:

  1. {'id': '17153800364953537565', 'title': '蜜雪冰城(南锣鼓巷店)', 'address': '北京市东城区鼓楼东大街164号(工商银行与穿行体育中间)', 'tel': '13520051612', 'category': '美食:冷饮店', 'type': 0, 'location': {'lat': 39.940685, 'lng': 116.400879}, 'ad_info': {'adcode': 110101, 'province': '北京市', 'city': '北京市', 'district': '东城区'}}
  2. {'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': '东城区'}}
  3. {'id': '17783258983880652103', 'title': '蜜雪冰城(簋街店)', 'address': '北京市东城区东直门内大街178号', 'tel': '17330593555', 'category': '美食:冷饮店', 'type': 0, 'location': {'lat': 39.94083, 'lng': 116.423554}, 'ad_info': {'adcode': 110101, 'province': '北京市', 'city': '北京市', 'district': '东城区'}}
  4. {'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': '东城区'}}
  5. ... ...
2. 将数据导入 Elasticsearch

环境:

  • Elasticsearch 7.17.0
  • Kibana 7.17.0
2.1 创建索引

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

  1. PUT /mxbc
  2. {
  3. "settings":{
  4. "number_of_shards" : 1,
  5. "number_of_replicas" : 0
  6. },
  7. "mappings": {
  8. "properties": {
  9. "id":{"type":"text"},
  10. "title":{"type":"keyword"},
  11. "address":{"type":"text"},
  12. "tel":{"type":"text"},
  13. "category":{"type":"text"},
  14. "type":{"type":"integer"},
  15. "location" : {"type" : "geo_point"},
  16. "adcode":{"type":"keyword"},
  17. "province":{"type":"text"},
  18. "city":{"type":"text"},
  19. "district":{"type":"keyword"}
  20. }
  21. }
  22. }

创建成功:

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

  1. curl --user 'username':'password' -X PUT "192.168.198.145:9200/mxbc2?pretty" -H 'Content-Type: application/json' -d'
  2. {
  3. "settings":{
  4. "number_of_shards" : 1,
  5. "number_of_replicas" : 0
  6. },
  7. "mappings": {
  8. "properties": {
  9. "id":{"type":"text"},
  10. "title":{"type":"keyword"},
  11. "address":{"type":"text"},
  12. "tel":{"type":"text"},
  13. "category":{"type":"text"},
  14. "type":{"type":"integer"},
  15. "location" : {"type" : "geo_point"},
  16. "adcode":{"type":"keyword"},
  17. "province":{"type":"text"},
  18. "city":{"type":"text"},
  19. "district":{"type":"keyword"}
  20. }
  21. }
  22. }
  23. '

创建过程如下:

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

2.2 整理格式

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

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

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

  1. # head bulk.txt
  2. {"index":{"_index":"mxbc"}}
  3. {'id': '17153800364953537565', 'title': '蜜雪冰城(南锣鼓巷店)', 'address': '北京市东城区鼓楼东大街164号(工商银行与穿行体育中间)', 'tel': '13520051612', 'category': '美食:冷饮店', 'type': 0, 'location': {'lat': 39.940685, 'lng': 116.400879}, 'ad_info': {'adcode': 110101, 'province': '北京市', 'city': '北京市', 'district': '东城区'}}
  4. {"index":{"_index":"mxbc"}}
  5. {'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': '东城区'}}
  6. {"index":{"_index":"mxbc"}}
  7. {'id': '17783258983880652103', 'title': '蜜雪冰城(簋街店)', 'address': '北京市东城区东直门内大街178号', 'tel': '17330593555', 'category': '美食:冷饮店', 'type': 0, 'location': {'lat': 39.94083, 'lng': 116.423554}, 'ad_info': {'adcode': 110101, 'province': '北京市', 'city': '北京市', 'district': '东城区'}}
  8. {"index":{"_index":"mxbc"}}
  9. {'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': '东城区'}}
  10. {"index":{"_index":"mxbc"}}
  11. {'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,同时单引号需要变换成双引号,否则后面无法导入:

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

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

  1. 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,按步骤设置,即可聚合门店数量

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

最后放一张俯视图结束:

相关文章