irpas技术客

Python获取最新省市区列表并绘制中国地图(含港澳台)_XerCis_python 省市

网络 4376

文章目录 简介安装初试响应结果直接展示构造字典树结构展示tkinter展示绘制成图参考文献

简介

数据来源:

省、市、区:腾讯 API省、市、区、街道、社区:国家统计局

安装 pip install requests

初试

使用腾讯 API

1. 注册

2. 我的应用 → 创建应用 3. 添加 Key:Key名称随意,启用产品 WebServiceAPI,选签名校验,复制 Secret key 4. 复制 Key 5. 获取最新省市区列表并保存为JSON

import json from hashlib import md5 from urllib.parse import urljoin, urlencode import requests key = 'JYRBZ-6B7WQ-SKG52-GKT6U-INYEH-OTB2B' secret_key = 'qhiND3JeHmFJTPk0HliqClqWn1ytmHqd' path = '/ws/district/v1/list' base = 'https://apis.map.qq.com/' url = urljoin(base, path) params = dict(key=key) params = {k: v for k, v in sorted(params.items())} # 升序排序 sig = md5('{}?{}{}'.format(path, urlencode(params), secret_key).encode()).hexdigest() # 签名计算 params['sig'] = sig # 放回请求 response = requests.get(url=url, params=params) data = response.json() print(data) open('data.json', mode='w', encoding='utf-8').write(json.dumps(data))

效果

响应结果

data_version:行政区划数据版本

result 的结果:

行政区划 id:行政区划唯一标识(adcode)name:简称,如“内蒙古”fullname:全称,如“内蒙古自治区”location:经纬度 lat:纬度lng:经度 pinyin:行政区划拼音全拼的数组,如:[“nei”,“meng”,“gu”]cidx:子级行政区划在下级数组中的下标位置polygon:行政区划的轮廓经纬度点串,可形成多边形

直接展示 import json data = json.load(open('data.json')) data_version = data['data_version'] print(data_version) provinces = data['result'][0] citys = data['result'][1] districts = data['result'][2] for province in provinces: cidx = province['cidx'] province_citys = citys[cidx[0]:cidx[1]] print(province['fullname']) for city in province_citys: print('\t', city['fullname']) cidx = city.get('cidx') if cidx: city_districts = districts[cidx[0]:cidx[1]] for district in city_districts: print('\t\t', district['fullname']) # 广东省 # 广州市 # 荔湾区 # 越秀区 # 海珠区 # 天河区 # 白云区 # 黄埔区 # 番禺区 # 花都区 # 南沙区 # 从化区

构造字典 import json from collections import defaultdict data = json.load(open('data.json')) provinces = data['result'][0] citys = data['result'][1] districts = data['result'][2] province_city_district_map = defaultdict(lambda: defaultdict(list)) for province in provinces: cidx = province['cidx'] province_citys = citys[cidx[0]:cidx[1]] for city in province_citys: if city['fullname'] not in province_city_district_map[province['fullname']]: province_city_district_map[province['fullname']][city['fullname']] = list() cidx = city.get('cidx') if cidx: city_districts = districts[cidx[0]:cidx[1]] for district in city_districts: province_city_district_map[province['fullname']][city['fullname']].append(district['fullname']) print(province_city_district_map)

树结构展示

安装

pip install treelib

代码

import json from treelib import Tree data = json.load(open('data.json')) data_version = data['data_version'] provinces = data['result'][0] citys = data['result'][1] districts = data['result'][2] tree = Tree() tree.create_node('中国省市区列表', data_version) # 根节点 for province in provinces: cidx = province['cidx'] province_citys = citys[cidx[0]:cidx[1]] tree.create_node(province['fullname'], province['id'], parent=data_version) for city in province_citys: tree.create_node(city['fullname'], city['id'], parent=province['id']) cidx = city.get('cidx') if cidx: city_districts = districts[cidx[0]:cidx[1]] for district in city_districts: tree.create_node(district['fullname'], district['id'], parent=city['id']) tree.show() # ├── 广东省 # │ ├── 东莞市 # │ ├── 中山市 # │ ├── 佛山市 # │ │ ├── 三水区 # │ │ ├── 南海区 # │ │ ├── 禅城区 # │ │ └── 顺德区

统计,有某些区名是重复的

from collections import Counter counter = Counter([tree[node].tag for node in tree.expand_tree(mode=Tree.DEPTH, sorting=False)]) print(counter) # Counter({'东区': 6, '鼓楼区': 4, '市中区': 4, '北区': 4, '和平区': 3, '新华区': 3, '城区': 3, '郊区': 3, '铁西区': 3, '中山区': 3, '南区': 3, '朝阳区': 2, '通州区': 2, '河东区': 2, '长安区': 2, '桥西区': 2, '复兴区': 2, '新城区': 2, '青山区': 2, '松山区': 2, '铁东区': 2, '海州区': 2, '太平区': 2, '龙潭区': 2, '西安区': 2, '向阳区': 2, '南山区': 2, '东山区': 2, '宝山区': 2, '大同区': 2, '新兴区': 2, '普陀区': 2, '金山区': 2, '西湖区': 2, '江北区': 2, '永定区': 2, '泰山区': 2, '白云区': 2, '龙华区': 2, '城中区': 2, '大安区': 2, '西区': 2, '城关区': 2, '新市区': 2, '中正区': 2, '信义区': 2, '中西区': 2})

tkinter展示 import json from tkinter import * from tkinter import ttk from collections import defaultdict data = json.load(open('data.json')) provinces = data['result'][0] citys = data['result'][1] districts = data['result'][2] province_fullnames = [] province_city_district_map = defaultdict(lambda: defaultdict(list)) for province in provinces: province_fullnames.append(province['fullname']) cidx = province['cidx'] province_citys = citys[cidx[0]:cidx[1]] for city in province_citys: if city['fullname'] not in province_city_district_map[province['fullname']]: province_city_district_map[province['fullname']][city['fullname']] = list() cidx = city.get('cidx') if cidx: city_districts = districts[cidx[0]:cidx[1]] for district in city_districts: province_city_district_map[province['fullname']][city['fullname']].append(district['fullname']) last_province = '' # 上次选择的省 last_city = '' # 上次选择的市 def select_province(event): """选择了省""" global last_province province = province_combobox.get() city_combobox['value'] = [i for i in province_city_district_map[province].keys()] if last_province != province: city_combobox.set('') district_combobox.set('') last_province = province def select_city(event): """选择了市""" global last_city province = province_combobox.get() city = city_combobox.get() district_combobox['value'] = province_city_district_map[province][city] if last_city != city: district_combobox.set('') last_city = city win = Tk() win.title('中国省市区列表') win.geometry('280x130') win.eval('tk::PlaceWindow . center') province_combobox = ttk.Combobox(win, value=province_fullnames) province_combobox.bind('<<ComboboxSelected>>', select_province) province_combobox.pack(fill=BOTH, expand=True) city_combobox = ttk.Combobox(win) city_combobox.bind('<<ComboboxSelected>>', select_city) city_combobox.pack(fill=BOTH, expand=True) district_combobox = ttk.Combobox(win) district_combobox.pack(fill=BOTH, expand=True) statusbar = Label(win, text='数据版本:{}'.format(data['data_version']), bd=1, relief=SUNKEN, anchor=W, name='statusbar') statusbar.pack(side=BOTTOM, fill=X) win.mainloop()

效果

绘制成图

获取数据

import json from hashlib import md5 from urllib.parse import urljoin, urlencode import requests key = 'JYRBZ-6B7WQ-SKG52-GKT6U-INYEH-OTB2B' secret_key = 'qhiND3JeHmFJTPk0HliqClqWn1ytmHqd' path = '/ws/district/v1/getchildren' base = 'https://apis.map.qq.com/' url = urljoin(base, path) params = dict(key=key, get_polygon=2) params = {k: v for k, v in sorted(params.items())} # 升序排序 sig = md5('{}?{}{}'.format(path, urlencode(params), secret_key).encode()).hexdigest() # 签名计算 params['sig'] = sig # 放回请求 response = requests.get(url=url, params=params) data = response.json() print(data) open('polygon.json', mode='w', encoding='utf-8').write(json.dumps(data))

安装

pip install basemap

绘制

import json import matplotlib.pyplot as plt from matplotlib.patches import Polygon from mpl_toolkits.basemap import Basemap def get_mass_center(xy): """计算多边形重心""" area = 0.0 x, y = 0.0, 0.0 for i in range(len(xy)): lat = xy[i][0] lng = xy[i][1] if i == 0: lat1 = xy[-1][0] lng1 = xy[-1][1] else: lat1 = xy[i - 1][0] lng1 = xy[i - 1][1] fg = (lat * lng1 - lng * lat1) / 2.0 area += fg x += fg * (lat + lat1) / 3.0 y += fg * (lng + lng1) / 3.0 x = x / area y = y / area return x, y # 读取 data = json.load(open('polygon.json')) province_polygon_map = dict() for province in data['result'][0]: province_polygon_map[province['name']] = province['polygon'] # 中文 plt.rcParams['font.sans-serif'] = ['SimHei'] # 微软雅黑 plt.rcParams['axes.unicode_minus'] = False # 正确显示负号 # 绘制 m = Basemap( llcrnrlon=77, llcrnrlat=14, # 左下角经纬度 urcrnrlon=140, urcrnrlat=51, # 右上角经纬度 projection='lcc', # 地图投影方式为朗伯等角圆锥投影 lat_0=33, # 纬度中心 lon_0=100 # 经度中心 ) m.fillcontinents(color='white') # 填充大陆 for province, polygons_list in province_polygon_map.items(): xy_list = [] # 行政区多个多边形的所有点 for polygons in polygons_list: xy = [] for i in range(len(polygons))[::2]: # 经纬度多边形 xy_list.append((polygons[i], polygons[i + 1])) xy.append(m(polygons[i], polygons[i + 1])) plt.gca().add_patch(Polygon(xy)) x, y = get_mass_center(xy_list) # 多边形重心 x = x - 1.2 # 手动修正 y = y - 0.5 plt.annotate(province, xy=m(x, y)) # 填上省份 print(province, x, y) plt.annotate('海南', xy=m(108.0, 19.0)) # 不知道为什么API获取的海南好像有问题,手动填入 plt.xticks([]) # 去掉x轴 plt.yticks([]) # 去掉y轴 plt.axis('off') # 去掉坐标轴 plt.savefig('1.jpg', dpi=300, bbox_inches='tight') # 保存图片 plt.show()

对比百度地图

参考文献 WebService API | 腾讯位置服务国家统计局 - 统计用区划和城乡划分代码2021最新省市区 Gitee最全最新中国省,市,地区json及sql数据 GitHubPython树结构库treelibMatplotlib Basemap Toolkit Documentationpython采用Basemap绘制完美中国地图python 不规则多边形计算重心How to compute the centroid of a polygon in PythonShapely Ddocumentation判断点是否在多边形内的Python实现及小应用(射线法)


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #Python #省市