老板们,你们每天上班的代步工具是什么呢?我每天上下班要换乘三班地铁,今天上班摸鱼就想着绘制一下所在城市的地铁线路图,有兴趣的小老板们一起先来看看效果图吧!
获取数据
1.首先我们打开高德地图的地铁网页如下:
http://map.amap.com/subway/index.html?&1100
2. 获取到的是一个json数据集,可以看到我们想要获取的数据就是每一个地铁站的坐标,也就是图中的sl标签下的数据。
3. 我们先是用爬虫将所有的坐标打印出来。
url ='http://map.amap.com/service/subway?_1620623429768&srhdata=6101_drw_xian.json'
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4484.7 Safari/537.36',
'Referer':'http://map.amap.com/subway/index.html?&1100',
'Cookie':'UM_distinctid=17954ac8d5e5e-0ac20e2913b1e6-71153641-1fa400-17954ac8d5f7ba; CNZZDATA1255672570=1041388408-1620620633-%7C1620620633; connect.sess=s%3Aj%3A%7B%7D.DffclZ%2FN%2BAiqU5kXMjqg3VQHapScLmBFjbTUDpqgPVQ'
}
resp = requests.get(url, headers).json()
stations = []
foriinresp['l']:
station = []
foraini['st']:
station.append([float(b)forbina['sl'].split(',')])
stations.append(station)
print('高德地图坐标:',stations)
'''
高德地图部分坐标: [[[108.753079, 34.320229], [108.763291, 34.317347], [108.777618, 34.313193], [108.79676, 34.307257], [108.813536, 34.300164], [108.832212, 34.289958], [108.85242, 34.284382], [108.862601, 34.279195], [108.873971, 34.273042], [108.892467, 34.269363], [108.909781, 34.26954], [108.920911, 34.269614], [108.933825, 34.269705], [108.947165, 34.269927], [108.962896, 34.270019], [108.974075, 34.269971], [108.984468, 34.269485], [108.995383, 34.269755], [109.013057, 34.269596], [109.030418, 34.27209], [109.04443, 34.27398], [109.056131, 34.275484], [109.069751, 34.279465]], [[108.753079, 34.320229], [108.763291, 34.317347], [108.777618, 34.313193], [108.79676, 34.307257], [108.813536, 34.300164], [108.832212, 34.289958], [108.85242, 34.284382], [108.862601, 34.279195], [108.873971, 34.273042], [108.892467, 34.269363], [108.909781, 34.26954]]]
'''
转换坐标系
我们是在高德地图中得到的这些坐标系,但是在百度地图中是不适用的。我们可以取同一坐标[108.947182,34.270022]对比来看一下:
百度地图显示西安一未知位置。
高德地图显示的是北大街地铁站
为什么会出现这个问题呢?
其实是不同地图产品的地理坐标系导致的。
下面说一下常见的地理坐标系:地球坐标系是国际通用坐标系,比较适合国际地图可视化。不过在我国范围内,一般不会直接使用它,而是使用由国家测绘局在其基础上加密的火星坐标系。另外还有公司会在火星坐标系上进行二次加密,比如百度坐标系、搜狗坐标系等。
所以我们还是需要将高德地图坐标转换成百度地图坐标。但是我们参考什么样的指标转呢?按照什么样的方法转呢?不着急往下看。
1、百度地图
1)境内(包括港澳台):BD09
a、在GCJ-02坐标系基础上再次加密
b、支持WGS-84、GCJ-02转换成BD09,反向不支持,并且批量转换一次有条数限制
2)境外:WGS-84
2、高德地图:
1)境内:GCJ-02
a、WGS-84——>GCJ-02(高德有接口提供,反过来没有)
2)境外:暂不支持
3)AMap 就是高德地图,是高德地图在纳斯达克上市用的名字,主要面向互联网企业或个人提供免费API服务
4)MapABC 是高德集团底下的图盟公司,主要面向大众型企业或政府机关,并提供付费的有偿服务
5)Amap和MapABC,数据和服务都是共享的,所以Mapabc用Amap的API是正常的
3、google地图
1)境内:GCJ-02
a、数据来源于高德,两者互通
2)境外:WGS-84
4、天地图
全球统一:CGCS2000
5、腾讯地图:soso地图
境内:GCJ02
6、微软bing地图:BingMap
全球统一:WGS-84
7、搜狗地图
境内:搜狗坐标系
a、在GCJ-02坐标系基础上再次加密
b、支持WGS-84、GCJ-02、BD09转换成搜狗坐标,反向不支持
8、图吧地图: MapBar
境内:图吧坐标系
a、在GCJ-02坐标系基础上再次加密
9、阿里云地图
境内:GCJ-02
10、灵图地图:51ditu
境内:GCJ-02
我们是在高德地图中获得的坐标点集合,那么也就是使用的是GCJ-02坐标系。而下文可视化中会调用百度地图的接口,也就是需要在BD-09坐标系中进行可视化。
原理搞清楚了接下来就是转换数据的时候了,这是我在网上找的转换方式:
#需要的两个常量先设置好
pi =3.1415926535897932384#π
r_pi = pi *3000.0/180.0
defgcj02_bd09(lon_gcj02,lat_gcj02):
b = math.sqrt(lon_gcj02 * lon_gcj02 + lat_gcj02 * lat_gcj02) +0.00002* math.sin(lat_gcj02 * r_pi)
o = math.atan2(lat_gcj02 , lon_gcj02) +0.000003* math.cos(lon_gcj02 * r_pi)
lon_bd09 = b * math.cos(o) +0.0065
lat_bd09 = b * math.sin(o) +0.006
return[lon_bd09,lat_bd09]
百度地图部分坐标: [[[108.75959575578001,34.326176701482076], [108.76985436017196,34.323136986125306], [108.78421348443841,34.31886710254733], [108.80331396734627,34.31304470276292], [108.82000062044823,34.30621891279717], [108.83859848911568,34.29625171486625], [108.8588198824655,34.290636155391276], [108.8690460444563,34.28531331133953], [108.88048018636168,34.27897078711726], [108.89905293121258,34.27505857891147], [108.91636147982514,34.27525231392642], [108.92744889734588,34.275461402089825], [108.94029526433305,34.27576709370141], [108.95357506954068,34.27617979022594], [108.96928481340704,34.276339132250286], [108.98048935350972,34.276210097495664], [108.9909295451151,34.27557552642388], [109.00190226809458,34.275661120806355], [109.01964390127117,34.27528744570549], [109.03699460743354,34.27780682956484], [109.05094681213411,34.279881932019975], [109.06258472578659,34.28158288607949], [109.07614636696833,34.285741107145675]], [[108.75959575578001,34.326176701482076], [108.76985436017196,34.323136986125306], [108.78421348443841,34.31886710254733], [108.80331396734627,34.31304470276292], [108.82000062044823,34.30621891279717], [108.83859848911568,34.29625171486625], [108.8588198824655,34.290636155391276], [108.8690460444563,34.28531331133953], [108.88048018636168,34.27897078711726], [108.89905293121258,34.27505857891147], [108.91636147982514,34.27525231392642], [108.92744889734588,34.275461402089825], [108.94029526433305,34.27576709370141], [108.95357506954068,34.27617979022594], [108.96928481340704,34.276339132250286], [108.98048935350972,34.276210097495664], [108.9909295451151,34.27557552642388], [109.00190226809458,34.275661120806355], [109.01964390127117,34.27528744570549], [109.03699460743354,34.27780682956484], [109.05094681213411,34.279881932019975], [109.06258472578659,34.28158288607949], [109.07614636696833,34.285741107145675]], [[108.75959575578001,34.326176701482076], [108.76985436017196,34.323136986125306], [108.78421348443841,34.31886710254733], [108.80331396734627,34.31304470276292], [108.82000062044823,34.30621891279717], [108.83859848911568,34.29625171486625], [108.8588198824655,34.290636155391276], [108.8690460444563,34.28531331133953], [108.88048018636168,34.27897078711726], [108.89905293121258,34.27505857891147], [108.91636147982514,34.27525231392642], [108.92744889734588,34.275461402089825], [108.94029526433305,34.27576709370141], [108.95357506954068,34.27617979022594], [108.96928481340704,34.276339132250286], [108.98048935350972,34.276210097495664], [108.9909295451151,34.27557552642388], [109.00190226809458,34.275661120806355], [109.01964390127117,34.27528744570549], [109.03699460743354,34.27780682956484], [109.05094681213411,34.279881932019975]]]]
可视化部分
接下来就要利用pyecharts中的BMap来可视化了,不过需要先获取百度开放平台的密钥。
百度地图开放平台:
http://lbsyun.baidu.com/apiconsole/key#/home
登录百度账户,查看应用管理-我的应用。点击创建应用,全部默认随便创建。
导入转换后的数据之后替换自己baidu_ak 即可。
map_b = (
BMap(init_opts = opts.InitOpts(width ="800px", height ="600px"))
.add_schema(
baidu_ak ='**********',#百度地图开发应用appkey
center = [108.947122,34.267899],#当前视角的中心点
zoom =10,#当前视角的缩放比例
is_roam =True,#开启鼠标缩放和平移漫游
)
.add(
series_name ="",
type_ = ChartType.LINES,#设置Geo图类型
data_pair = result,#数据项
is_polyline =True,#是否是多段线,在画lines图情况下#
linestyle_opts = opts.LineStyleOpts(color ="blue", opacity =0.5, width =1),# 线样式配置项
)
.add_control_panel(
maptype_control_opts = opts.BMapTypeControlOpts(type_ = BMapType.MAPTYPE_CONTROL_DROPDOWN),#切换地图类型的控件
scale_control_opts = opts.BMapScaleControlOpts(),#比例尺控件
overview_map_opts = opts.BMapOverviewMapControlOpts(is_open =True),#添加缩略地图
navigation_control_opts = opts.BMapNavigationControlOpts()#地图的平移缩放控件
)
)
map_b.render(path ='subway_西安.shtml')
最终效果图如下:
看到你坐的那一趟地铁了吗?
网友评论