最近做规划项目,领导让查出某几个市的所有乡镇级行政区域,距离所在县级行政中心的交通运输距离。想着也不是啥难事儿,高德地图一搜就有。
当我把各市行政区划统计完,发现一共有五百多个乡镇,意味着要在地图上搜索五百多次,立马脑仁疼。
于是我把任务分工给了其他同事,几个人同时查,能快点。
看看,思维就是这么僵化,没有立刻意识到重复劳动也许可以借助计算机来自动完成。
边查数据边想,以后还会有此类任务,到时候没同事帮忙可咋办,虽然不费脑力,却消耗大量时间。忽然意识到,我会基本的 Python 啊,搜搜网上有没有自动查距离的教程。
果然搜到一篇文章,《Python 批量获取高德地图地理信息数据》。然后参考博主的代码,写了一个自动从高德地图获取地理经纬度和运输距离的 Python 脚本,配合 xlxs 格式文件使用,可批量查找数据并存储进 xlxs 格式文件。
在 高德开放平台 上注册一个帐号,然后创建一个 web 服务类型的应用,再给该应用添加一个密钥 key,记住这个 key。
创建一个 xlsx 格式文件,命名为 workbook。将需要查询的地名放进 workbook.xlsx 的 Sheet1 工作表中,Python 脚本自动获取的经纬度和运输距离将写入 Sheet2 工作表中。因此该文件中需已存在 Sheet1 和 Sheet2 两个工作表。
Sheet1 中按下图格式填写地名。每个县级行政区域内的地名放置一列,第一行为该县级行政区域名称,第二行及之后为其下乡镇级行政区域名称。写入的地名必须全部属于一个地级市。如果要获取多个市的数据,只能先写入一个市,运行完脚本后,再对另一个市重复操作。
安装 Python 环境不表。
利用 Python 的 openpyxl 库从 xlsx 格式文件中读写数据,因此先安装此库。
pip install openpyxl
新建一个 py 脚本文件,名称随意,如 workscript.py,用文本编辑器打开,将以下代码复制进去保存。该脚本文件应与 workbook.xlsx 在同一目录中。
# 对 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 中。如下图所示,第一列为地名,第二列为经纬度,第三列为该乡镇到所在县级行政中心的运输距离。如果是县名,第三列则标注「行政中心」。
本文作者:tsingk
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!