Python 省市转换百度经纬度并显示数据热力图
  wuqQcfl7z3Ys 2023年11月13日 81 0


刚好本地数据库有各省市县/区的数据,现在打算统计一下各个城市的县区数量,并以热力图在地图上显示。(部分数据如下)

Python 省市转换百度经纬度并显示数据热力图_html

本测试使用的是百度地图,首先先到百度地图开发平台注册一个个人开发账号。然后创建两个用于:服务端和浏览器端,每个应用都会有一个访问应用(AK),属于个人私钥。服务端应用主要用于根据城市读取经纬度,浏览器端应用主要用于地图显示,这两个的应用别搞错。(可能错误:百度未授权使用地图API)

对于经纬度根据地名的提取,接口地址如下:

http://api.map.baidu.com/geocoder/v2/?address=地址&output=json&ak=百度AK

返回结果:

{"status":0,"result":{"location":{"lng":114.0259736573215,"lat":22.546053546205248},"precise":0,"confidence":14,"level":"城市"}}

地图的选择,使用的是热力图,链接地址如下:

http://developer.baidu.com/map/jsdemo.htm#c1_15 

Python 省市转换百度经纬度并显示数据热力图_json_02

地图上有个默认示例,其中“你的密钥”就是 个人的浏览器端AK,页面中还有一个 json 格式的变量 points,存储的是数据,格式如:

var points =[
    {"lng":116.418261,"lat":39.921984,"count":50},
    {"lng":116.423332,"lat":39.916532,"count":51},
    {"lng":116.419787,"lat":39.930658,"count":15},
    {"lng":116.42076,"lat":39.915251,"count":70},
    {"lng":116.425867,"lat":39.918989,"count":8}];

使用的时候可以把中间这个页面的源码拷贝下来,创建一个 html 的文件,然后更改 ak 及 相关数据,双击打开即可关联到百度地图中显示。不过用python一键操作更方便一点。



再说说地图的显示级别及默认显示位置。因为是全国显示,可以把中心经纬度改为重庆,显示级别改为5。

var point = new BMap.Point(116.418261, 39.921984); #默认定位坐标天安门
map.centerAndZoom(point, 15);  //显示级别默认为15

其中,显示级别可以从这确定:

http://api.map.baidu.com/lbsapi/getpoint/index.html


由于用 python 识别读取网页中的代码下载,使用的是 selenium ,selenium 模拟使用浏览器打开网页,脚本设置打开浏览器是在后台执行的。(更多参考:Python selenium 后台运行模拟登录操作)


完整脚本如下:(ak 改用自己的哈)

import os
import re
import time
import json
import sqlalchemy  
import webbrowser
import pandas as pd
from selenium import webdriver
from urllib.request import urlopen, quote

centerAndZoom = 5 #地图显示级别(比例)
filepath = "./map.html" # html下载位置
ak_browser = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" #浏览器AK:用于地图显示
ak_server  = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" #服务端AK:用于获取经纬度
chromedriver = 'D:/Python35/mypy/phantomjs/bin/phantomjs.exe' 
driver = webdriver.PhantomJS(chromedriver)  
engine = sqlalchemy.create_engine("mssql+pymssql://kk:kk@HYH0109-189\CAT2014/CSMS3")

#下载百度热力图HTML模板到本地
def download_baidu_map_html():
	url = "http://developer.baidu.com/map/jsdemo.htm#c1_15" #热力图模板
	driver.get(url)
	driver.maximize_window()
	time.sleep(2)
	#driver.get_screenshot_as_file("./screen.png") 
	html = driver.find_element_by_xpath("//div[@class='CodeMirror-code']")
	with open("./map.html", "w", encoding="utf-8") as f:
		f.write(html.text)
	f.close

#用自己的数据替换HTML原有的数据
def put_data_into_html(df):
	#df.rename(columns={'Longitude': 'lng', 'Latitude': 'lat', 'DistrictCount': 'count'}, inplace=True)
	points_json  = df[['lng','lat','count']].to_json(orient='records')[1:-1].replace('},{', '},\n{')
	f = open(filepath, "r", encoding="utf-8")
	lines = f.readlines()
	f.close()
	contents = ""
	for line in lines:
		if not re.match("(.+)lng(.+)lat(.+)count(.+)", line):
			if re.match("(.+)您的密钥(.+)", line):
				line = line.replace('您的密钥', ak_browser) #将ak替换
			if  re.match("(.+)enableScrollWheelZoom(.+)", line):
				#该行"var points =[" 从网页下载时没有,所以手动补全!
				line = line + "\n var points =[\n" + points_json + "];\n" #将数据替换
			if  re.match("(.+)map.centerAndZoom(.+)", line):
				line = re.sub("\d+", "%s" % centerAndZoom ,line)  #地图级别
			contents = contents + line
	f2 = open(filepath,"w", encoding="utf-8")
	f2.write(contents)
	f2.close
	
#从数据库获取:省、市、市的地区数量	
def get_data_from_db():  
	sql = """SELECT A.Name AS Provicne,B.Name AS City,COUNT(*) AS [count]
	FROM SysRegion A 
	INNER JOIN SysRegion B ON A.Id=B.ParentId AND A.LevelType=1
	INNER JOIN SysRegion C ON B.Id=C.ParentId AND B.LevelType=2
	GROUP BY A.Name,B.Name"""  
	df = pd.read_sql_query(sql, engine)  
	return df

#根据省市从百度地图中获取经纬度
def get_lng_lat_from_baidu(address):
	address = quote(address) #中文转码
	url = "http://api.map.baidu.com/geocoder/v2/"
	url = url + "?address=%s&output=json&ak=%s" %(address,ak_server)
	res = json.loads(urlopen(url).read().decode())
	return res

#经纬度添加到原 pd 中
def get_df_parse_json(df):
	for index, row in df.iterrows():
		js = get_lng_lat_from_baidu(row['Provicne']+row['City'])
		if (js['status'] == 0):
			df.loc[index, 'lng'] = js['result']['location']['lng']
			df.loc[index, 'lat'] = js['result']['location']['lat']
	return df

def open_html_on_browser():
	htmlfile = os.path.abspath(filepath)
	htmlfile = 'file:///' + htmlfile.replace("\\","/")
	webbrowser.open_new_tab(htmlfile)
	
if __name__ == "__main__":
	df = get_data_from_db() #从数据库获取:省、市、市的地区数量	
	df = get_df_parse_json(df) #经纬度添加到原 pd 中
	download_baidu_map_html() #下载百度热力图HTML模板到本地
	put_data_into_html(df) #用自己的数据替换HTML原有的数据
	open_html_on_browser() #打开HTML地图预览


结果如上图,当几个地点靠的很近,且数据量加起来较多时,会形成一个重点区域,如图中的红色或绿色区域。


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月13日 0

暂无评论

推荐阅读
wuqQcfl7z3Ys