查看原文
其他

Python绘制炫酷的西安地铁动图,你每天坐的是哪条线呢?

是沐沐呀 GOGO数据 2022-08-01

老板们,你们每天上班的代步工具是什么呢?我每天上下班要换乘三班地铁,今天上班摸鱼就想着绘制一下所在城市的地铁线路图,有兴趣的小老板们一起先来看看效果图吧!



获取数据


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 = []
for i in resp['l']:
    station = []
    for a in i['st']:
        station.append([float(b) for b in a['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

def gcj02_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.7595957557800134.326176701482076], [108.7698543601719634.323136986125306], [108.7842134844384134.31886710254733], [108.8033139673462734.31304470276292], [108.8200006204482334.30621891279717], [108.8385984891156834.29625171486625], [108.858819882465534.290636155391276], [108.869046044456334.28531331133953], [108.8804801863616834.27897078711726], [108.8990529312125834.27505857891147], [108.9163614798251434.27525231392642], [108.9274488973458834.275461402089825], [108.9402952643330534.27576709370141], [108.9535750695406834.27617979022594], [108.9692848134070434.276339132250286], [108.9804893535097234.276210097495664], [108.990929545115134.27557552642388], [109.0019022680945834.275661120806355], [109.0196439012711734.27528744570549], [109.0369946074335434.27780682956484], [109.0509468121341134.279881932019975], [109.0625847257865934.28158288607949], [109.0761463669683334.285741107145675]], [[108.7595957557800134.326176701482076], [108.7698543601719634.323136986125306], [108.7842134844384134.31886710254733], [108.8033139673462734.31304470276292], [108.8200006204482334.30621891279717], [108.8385984891156834.29625171486625], [108.858819882465534.290636155391276], [108.869046044456334.28531331133953], [108.8804801863616834.27897078711726], [108.8990529312125834.27505857891147], [108.9163614798251434.27525231392642], [108.9274488973458834.275461402089825], [108.9402952643330534.27576709370141], [108.9535750695406834.27617979022594], [108.9692848134070434.276339132250286], [108.9804893535097234.276210097495664], [108.990929545115134.27557552642388], [109.0019022680945834.275661120806355], [109.0196439012711734.27528744570549], [109.0369946074335434.27780682956484], [109.0509468121341134.279881932019975], [109.0625847257865934.28158288607949], [109.0761463669683334.285741107145675]], [[108.7595957557800134.326176701482076], [108.7698543601719634.323136986125306], [108.7842134844384134.31886710254733], [108.8033139673462734.31304470276292], [108.8200006204482334.30621891279717], [108.8385984891156834.29625171486625], [108.858819882465534.290636155391276], [108.869046044456334.28531331133953], [108.8804801863616834.27897078711726], [108.8990529312125834.27505857891147], [108.9163614798251434.27525231392642], [108.9274488973458834.275461402089825], [108.9402952643330534.27576709370141], [108.9535750695406834.27617979022594], [108.9692848134070434.276339132250286], [108.9804893535097234.276210097495664], [108.990929545115134.27557552642388], [109.0019022680945834.275661120806355], [109.0196439012711734.27528744570549], [109.0369946074335434.27780682956484], [109.0509468121341134.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')


最终效果图如下:


老规矩,需要源码参考的小伙伴可以私我哈




精彩推荐

西安租房哪里房源最多?python可视化爬虫告诉你!

偷偷告诉你,西安五一发生的大事件……

Python自动发送邮件,1分钟搞定100份!

一入爬虫深似海,从此游戏是路人!硬核福利也有我一份!



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存