最近做规划项目,领导让查出某几个市的所有乡镇级行政区域,距离所在县级行政中心的交通运输距离。想着也不是啥难事儿,高德地图一搜就有。
当我把各市行政区划统计完,发现一共有五百多个乡镇,意味着要在地图上搜索五百多次,立马脑仁疼。
于是我把任务分工给了其他同事,几个人同时查,能快点。
看看,思维就是这么僵化,没有立刻意识到重复劳动也许可以借助计算机来自动完成。
边查数据边想,以后还会有此类任务,到时候没同事帮忙可咋办,虽然不费脑力,却消耗大量时间。忽然意识到,我会基本的 Python 啊,搜搜网上有没有自动查距离的教程。
果然搜到一篇文章,《Python 批量获取高德地图地理信息数据》。然后参考博主的代码,写了一个自动从高德地图获取地理经纬度和运输距离的 Python 脚本,配合 xlxs 格式文件使用,可批量查找数据并存储进 xlxs 格式文件。
准备工作#
1. 获取高德开放平台的应用密钥#
在 高德开放平台 上注册一个帐号,然后创建一个 web 服务类型的应用,再给该应用添加一个密钥 key,记住这个 key。
2. 处理 workbook.xlsx 文件#
创建一个 xlsx 格式文件,命名为 workbook。将需要查询的地名放进 workbook.xlsx 的 Sheet1 工作表中,Python 脚本自动获取的经纬度和运输距离将写入 Sheet2 工作表中。因此该文件中需已存在 Sheet1 和 Sheet2 两个工作表。
Sheet1 中按下图格式填写地名。每个县级行政区域内的地名放置一列,第一行为该县级行政区域名称,第二行及之后为其下乡镇级行政区域名称。写入的地名必须全部属于一个地级市。如果要获取多个市的数据,只能先写入一个市,运行完脚本后,再对另一个市重复操作。

3. 安装 Python 环境和 openpyxl 库#
安装 Python 环境不表。
利用 Python 的 openpyxl 库从 xlsx 格式文件中读写数据,因此先安装此库。
4. 创建 Python 脚本#
新建一个 py 脚本文件,名称随意,如 workscript.py,用文本编辑器打开,将以下代码复制进去保存。该脚本文件应与 workbook.xlsx 在同一目录中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
|
# 对 Sheet1 中多列数据求值,并将结果输出为 Sheet2 中一列
import urllib.request # 发送请求
from urllib import parse # URL 编码
import json # 解析 json 数据
from openpyxl import load_workbook # 从 Excel 中读取乡镇名称
def city_location(localname, somewhere, thekey):
url1 = (
'http://restapi.amap.com/v3/place/text?keywords=' + localname +
'&city=' + somewhere +
'&citylimit=true&output=json&offset=1&page=1&key=' + thekey
)
# 将一些符号进行 URL 编码
newUrl1 = parse.quote(url1, safe="/:=&?#+!$,;'@()*[]")
# 发送请求
response1 = urllib.request.urlopen(newUrl1)
# 读取数据
data1 = response1.read()
# 解析 json 数据
jsonData1 = json.loads(data1)
# 从 json 文件中提取座标
try:
a = jsonData1['pois'][0]['location']
except:
return '查询不到坐标'
else:
return a
def road_long(origin, destination, thekey):
url2 = (
'https://restapi.amap.com/v3/direction/driving?origin=' + origin +
'&destination=' + destination +
'&extensions=all&strategy=1&output=json&key=' + thekey
)
# 将一些符号进行 URL 编码
newUrl2 = parse.quote(url2, safe="/:=&?#+!$,;'@()*[]")
# 发送请求
response2 = urllib.request.urlopen(newUrl2)
# 接收数据
data2 = response2.read()
# 解析 json 文件
jsonData2 = json.loads(data2)
# 从 json 文件中提取距离
try:
a = jsonData2['route']['paths'][0]['distance']
except:
return '查询不到距离'
else:
return a
somewhere = input('地点所在地级市名称:')
thekey = input('高德开放平台密钥:')
book = load_workbook('workbook.xlsx')
nameSheet = book["Sheet1"]
locationsheet = book['Sheet2']
tol = 0
for index1 in range(ord('A'), ord('A')+nameSheet.max_column):
index1 = chr(index1)
nameList = []
for row in range(1, nameSheet.max_row+1):
nameList.append(nameSheet[index1+str(row)].value)
nameList = [x for x in nameList if x is not None] # 删除空字符
print(nameList)
dict1 = {} # 创建一个字典用于接收坐标数据
dict2 = {} # 创建一个字典用于接收距离数据
for cityname in nameList:
dict1[cityname] = city_location(cityname, somewhere, thekey)
for cityname in nameList[1::]:
if dict1[cityname] == '查询不到坐标':
dict2[cityname] = '此地查询不到坐标值'
else:
dict2[cityname] = road_long(
dict1[cityname], dict1[nameSheet[index1+'1'].value], thekey
)
dict2[nameSheet[index1+'1'].value] = '行政中心'
print(dict1)
print(dict2)
list1 = []
for cityname in nameList:
list2 = [cityname, dict1[cityname], dict2[cityname]]
list1.append(list2)
print(list1)
for row in range(len(nameList)):
(
locationsheet['A%d' % (row+1+tol)],
locationsheet['B%d' % (row+1+tol)],
locationsheet['C%d' % (row+1+tol)]
) = list1[row]
tol += len(nameList)
book.save('workbook.xlsx')
|
运行脚本获取数据#
使用终端在脚本目录下运行该脚本。会提示输入「地点所在地级市名称」和「高德开放平台密钥」。为避免全国范围内地名重复导致查询距离偏差,脚本将查询范围约束到乡镇所在的地级市,因此需要输入「地点所在地级市名称」。「高德开放平台密钥」则为之前创建的高德平台 web 服务应用 key。
输入完毕后,脚本开始从 workbook.xlsx 文件中读取地名,然后自动发送至高德地图查找经纬度和运输距离,再将数据保存到 workbook.xlsx 文件中。正常运行下,终端中也会显示获取到的数据。
待脚本运行完,打开 workbook.xlsx,所需要查找的运输距离就在工作表 Sheet2 中。如下图所示,第一列为地名,第二列为经纬度,第三列为该乡镇到所在县级行政中心的运输距离。如果是县名,第三列则标注「行政中心」。

高德地图查询两个地点之间的运输距离,需要提交两个地点的经纬度,因此脚本先从高德地图获取各个地点的经纬度,顺便保存在 Sheet2 中。
高德地图查询两个地点之间的运输距离,驾车路径规划有「距离有线」、「速度有线」、「费用优先」等策略,该脚本选择的是「费用优先」,即不走收费路段,且耗时最少的路线。
所查询距离单位为米。
一个高德开放平台key,一天只能查询2000次经纬度,2000次驾驶距离。所以如果查询地点超过2000个,要么多创建几个key,要么等第二天再查。