使用Python调用百度地图的API在地图上添加标记

写在前面

近期博主工作太忙,快一个月没更新博客。今天跑了大半天的腿,被一堆破事儿弄的无比憋屈,写篇博客调节一下心情。
博主的目的是在地图上做一些标记,然后保存为html网页文件,这样方便我的软件调用,前期我使用的folium包,这个包很强大,支持添加各种标记。但有几个缺点:

  • 地图的底图不支持百度地图,博主想用这个包的话,就不得不将数据点转到高德坐标系下,然后进行下一步工作,然而高德莫名其妙的封了我的账号,说我违规调取数据,简直莫须有;
  • 间歇性的出现一些未知的问题,比如添加的标记不显示等等,可以理解,毕竟外国人写的,也还不是很成熟;
  • 最要命的是地图加载太慢了,加载出来要接近一分钟。

想一想,既然数据点是百度坐标系下的,百度地图又提供了API,何不直接在百度地图上画呢。
好了,上编译环境。

  • Python3.7
  • Spyder

功能实现

API地址

先上百度地图js API地址
看看API示例:
在这里插入图片描述
语言是JavaScript,展示的界面是添加标记点,我把完整的示例代码贴出来,并解释一下:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <title>添加点标记</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge">
    <style>
    body,
    html,
    #container {
    
    
        overflow: hidden;
        width: 100%;
        height: 100%;
        margin: 0;
        font-family: "微软雅黑";
    }
    </style>
    <script src="//api.map.baidu.com/api?type=webgl&v=1.0&ak=您的密钥"></script>
</head>
<body>
    <div id="container"></div>
</body>
</html>
<script>
var map = new BMapGL.Map('container');
map.centerAndZoom(new BMapGL.Point(116.404, 39.928), 15);
map.enableScrollWheelZoom(true);
// 创建点标记
var marker1 = new BMapGL.Marker(new BMapGL.Point(116.404, 39.925));
var marker2 = new BMapGL.Marker(new BMapGL.Point(116.404, 39.915));
var marker3 = new BMapGL.Marker(new BMapGL.Point(116.395, 39.935));
var marker4 = new BMapGL.Marker(new BMapGL.Point(116.415, 39.931));
// 在地图上添加点标记
map.addOverlay(marker1);
map.addOverlay(marker2);
map.addOverlay(marker3);
map.addOverlay(marker4);
</script>

虽然博主没搞过JavaScript,不过语言大体相通,能看明白写的是什么,前面是网页的基础设置,主体在script标签中,定义了四个点,然后将这四个点添加到地图上。
官方给的示例其实是有问题的,我填上了自己申请的AK,另存为html文件后却怎么也打不开,于是初略看了下代码,发现下面这行就是个坑:

<script src="//api.map.baidu.com/api?type=webgl&v=1.0&ak=您的密钥">

我稍微改了下,改成了:

<script src="https://api.map.baidu.com/api?type=webgl&v=1.0&ak=您的密钥">

就能显示了,不过显示还是不完整,猜测是可能缺少加载 BMapGL.Map方法的js包,所以不再纠结,于是在网上找了另外一段可以执行的代码,链接在这里
这个代码也要加上https才行。有用的代码如下:

<!DOCTYPE html>
<html xmlns:asp="">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
    <style type="text/css">
        body, html,#allmap {
    
    width: 100%;height: 100%;overflow: hidden;margin:0;font-family:"微软雅黑";}
    </style>
    <script type="text/javascript" src="//api.map.baidu.com/api?type=webgl&v=1.0&ak=d5Y5C26Xbhr3rBHo3GzzaA7xcXev6NL0"></script>
    <title>添加信息窗口</title>
</head>
<body>
<div id="allmap"></div>
</body>
<script>
    // An highlighted block
    //百度地图API功能

    function loadJScript() {
    
    
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.src = "//api.map.baidu.com/api?v=2.0&ak=d5Y5C26Xbhr3rBHo3GzzaA7xcXev6NL0&callback=init";
        document.body.appendChild(script);
    }
    window.init = function() {
    
    
        var map = new BMap.Map("allmap");            // 创建Map实例
        //var point = new BMap.Point(109.18592,34.36912); // 创建点坐标
        map.centerAndZoom(new BMap.Point(109.19708,34.36820), 15);  // 设置中心点,地图初始化
        //map.centerAndZoom(points,20);
        map.setCurrentCity("西安");          //设置当前城市
        map.clearOverlays();
        map.addControl(new BMap.MapTypeControl());
        map.enableScrollWheelZoom(true);                 //启用滚轮放大缩小
       
        //向地图中添加缩放控件
        var ctrlNav = new window.BMap.NavigationControl({
    
    
            anchor: BMAP_ANCHOR_TOP_LEFT,
            type: BMAP_NAVIGATION_CONTROL_LARGE
        });
        map.addControl(ctrlNav);


		//向地图中添加标记点
        var myIcon =new BMap.Icon("http://api.map.baidu.com/img/markers.png", new BMap.Size(23, 25), {
    
        //小车图片
            offset: new BMap.Size(0, -5),    //相当于CSS精灵
            imageOffset: new BMap.Size(0, 0)    //图片的偏移量。为了是图片底部中心对准坐标点。
        });

        var points = [new BMap.Point(109.19474,34.36847),new BMap.Point(109.19435,34.37712),new BMap.Point(109.19261,34.37617),new BMap.Point(109.19701,34.37728),new BMap.Point(109.19702,34.37776),new BMap.Point(109.19784,34.37738),new BMap.Point(109.19784,34.376911),new BMap.Point(109.1987,34.37333),new BMap.Point(109.19705,34.36824),new BMap.Point(109.1836,34.37393)];   //10个坐标点

        var marker1 =new BMap.Marker(points[1],{
    
    icon:myIcon});  // 创建10个标注
        var marker2 =new BMap.Marker(points[2],{
    
    icon:myIcon});
        var marker3 =new BMap.Marker(points[3],{
    
    icon:myIcon});
        var marker4 =new BMap.Marker(points[4],{
    
    icon:myIcon});
        var marker5 =new BMap.Marker(points[5],{
    
    icon:myIcon});
        var marker6 =new BMap.Marker(points[6],{
    
    icon:myIcon});
        var marker7 =new BMap.Marker(points[7],{
    
    icon:myIcon});
        var marker8 =new BMap.Marker(points[8],{
    
    icon:myIcon});
        var marker9 =new BMap.Marker(points[9],{
    
    icon:myIcon});
        var marker0 =new BMap.Marker(points[0],{
    
    icon:myIcon});

        map.addOverlay(marker1);              // 将标注添加到地图中
        map.addOverlay(marker2);
        map.addOverlay(marker3);
        map.addOverlay(marker4);
        map.addOverlay(marker5);
        map.addOverlay(marker6);
        map.addOverlay(marker7);
        map.addOverlay(marker8);
        map.addOverlay(marker9);
        map.addOverlay(marker0);

        map.setViewport(points);         //调整地图的最佳视野为显示标注数组point        
    loadJScript()
</script>

<script>
    layui.use('theme/settings/earth', layui.factory('theme/settings/earth'));
</script>

<!--<script type="text/javascript" src="js\jquery-2.1.1.min.js"></script>-->

</html>

Python实现

好了,网页代码有了,可是博主并不会写html,只会简单的写写Python,如何把上面的代码合理的利用起来,并且将里面的变量改变成自己的点呢?
博主的思路很简单,将上面这些代码分成几个部分的字符串,然后字符串拼接起来,最后形成一个完整的html网页代码。
如果大家有仔细看上面的代码,会发现网页框架可以分成五部分:
第一部分代码:

    <!DOCTYPE html>
    <html xmlns:asp="">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
        <style type="text/css">
            body, html,#allmap {
    
    width: 100%;height: 100%;overflow: hidden;margin:0;font-family:"微软雅黑";}
        </style>
        <script type="text/javascript" src="https://api.map.baidu.com/api?type=webgl&v=1.0&ak=9Rz4tOb6PgQtqBt6K3YbSMBESLk8iYpE"></script>
        <title>添加信息窗口</title>
    </head>
    <body>
    <div id="allmap"></div>
    </body>
    <script>
        // An highlighted block
        //百度地图API功能

        function loadJScript() {
    
    
            var script = document.createElement("script");
            script.type = "text/javascript";
            script.src = "https://api.map.baidu.com/api?v=2.0&ak=9Rz4tOb6PgQtqBt6K3YbSMBESLk8iYpE&callback=init";
            document.body.appendChild(script);
        }
        window.init = function() {
    
    
            var map = new BMap.Map("allmap");            // 创建Map实例
            //var point = new BMap.Point(109.18592,34.36912); // 创建点坐标
            map.centerAndZoom(new BMap.Point(120.2338341,31.58109976), 15);  // 设置中心点,地图初始化
            //map.centerAndZoom(points,20);
            map.setCurrentCity("无锡");          //设置当前城市
            map.clearOverlays();
            map.addControl(new BMap.MapTypeControl());
            map.enableScrollWheelZoom(true);                 //启用滚轮放大缩小
            map.addEventListener('click', function(e) {
    
    
                alert('点击的经纬度:' + e.latlng.lng + ', ' + e.latlng.lat);
                var mercator = map.lnglatToMercator(e.latlng.lng, e.latlng.lat);
                alert('点的墨卡托坐标:' + mercator[0] + ', ' + mercator[1]);
            });
            //向地图中添加缩放控件
            var ctrlNav = new window.BMap.NavigationControl({
    
    
                anchor: BMAP_ANCHOR_TOP_LEFT,
                type: BMAP_NAVIGATION_CONTROL_LARGE
            });
            map.addControl(ctrlNav);


    		//向地图中添加标记点
            var myIcon =new BMap.Icon("http://api.map.baidu.com/img/markers.png", new BMap.Size(23, 25), {
    
        //小车图片
                offset: new BMap.Size(0, -5),    //相当于CSS精灵
                imageOffset: new BMap.Size(0, 0)    //图片的偏移量。为了是图片底部中心对准坐标点。
            });

这部分代码是基本不会变化的,改动无非就是那两个经纬度坐标和城市名。
再看第二部分:

var points = [new BMap.Point(109.19474,34.36847),new BMap.Point(109.19435,34.37712),new BMap.Point(109.19261,34.37617),new BMap.Point(109.19701,34.37728),new BMap.Point(109.19702,34.37776),new BMap.Point(109.19784,34.37738),new BMap.Point(109.19784,34.376911),new BMap.Point(109.1987,34.37333),new BMap.Point(109.19705,34.36824),new BMap.Point(109.1836,34.37393)];   //10个坐标点

这部分是定义的数据点,就是说如果要更换数据点,应该在这里改。
第三部分:

		var marker1 =new BMap.Marker(points[1],{
    
    icon:myIcon});  // 创建10个标注
        var marker2 =new BMap.Marker(points[2],{
    
    icon:myIcon});
        var marker3 =new BMap.Marker(points[3],{
    
    icon:myIcon});
        var marker4 =new BMap.Marker(points[4],{
    
    icon:myIcon});
        var marker5 =new BMap.Marker(points[5],{
    
    icon:myIcon});
        var marker6 =new BMap.Marker(points[6],{
    
    icon:myIcon});
        var marker7 =new BMap.Marker(points[7],{
    
    icon:myIcon});
        var marker8 =new BMap.Marker(points[8],{
    
    icon:myIcon});
        var marker9 =new BMap.Marker(points[9],{
    
    icon:myIcon});
        var marker0 =new BMap.Marker(points[0],{
    
    icon:myIcon});

第三部分是在为点添加标记,也是根据点来的,有多少点就写多少行。
第四部分:

        map.addOverlay(marker1);              // 将标注添加到地图中
        map.addOverlay(marker2);
        map.addOverlay(marker3);
        map.addOverlay(marker4);
        map.addOverlay(marker5);
        map.addOverlay(marker6);
        map.addOverlay(marker7);
        map.addOverlay(marker8);
        map.addOverlay(marker9);
        map.addOverlay(marker0);

第四部分是把标记点添加到map图层上去,也是根据自己的数据来的。
第五部分:

    loadJScript()
</script>

<script>
    layui.use('theme/settings/earth', layui.factory('theme/settings/earth'));
</script>

<!--<script type="text/javascript" src="js\jquery-2.1.1.min.js"></script>-->

</html>

这部分也不需要动。
既然代码已经分解清楚了,用Python来把这些代码串起来就很简单了,看看怎么实现的吧:

#!/usr/bin/env python
#-*- coding:utf-8 -*-
# author:HP
# datetime:2020/12/11 16:47
import pandas as pd

data = pd.read_csv('数据.txt', sep='\t')

def get_html(YearData):
    var_point = []
    var_marker = []
    addOverlay = []

    for i in range(len(YearData)):
        point = 'new BMap.Point(' + str(YearData.loc[i, 'lon_baidumap']) + ',' + str(YearData.loc[i, 'lat_baidumap']) + ')'
        marker = 'var marker' + str(i) + '=new BMap.Marker(points[' + str(i) + '],{icon:myIcon});'
        overlay = 'map.addOverlay(marker' + str(i) + ');'
        var_point.append(point)
        var_marker.append(marker)
        addOverlay.append(overlay)

    points = ','.join(var_point)
    markers = '\n        '.join(var_marker)
    overlays = '\n        '.join(addOverlay)

    message1 = '''
    <!DOCTYPE html>
    <html xmlns:asp="">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
        <style type="text/css">
            body, html,#allmap {width: 100%;height: 100%;overflow: hidden;margin:0;font-family:"微软雅黑";}
        </style>
        <script type="text/javascript" src="https://api.map.baidu.com/api?type=webgl&v=1.0&ak=9Rz4tOb6PgQtqBt6K3YbSMBESLk8iYpE"></script>
        <title>添加信息窗口</title>
    </head>
    <body>
    <div id="allmap"></div>
    </body>
    <script>
        // An highlighted block
        //百度地图API功能

        function loadJScript() {
            var script = document.createElement("script");
            script.type = "text/javascript";
            script.src = "https://api.map.baidu.com/api?v=2.0&ak=9Rz4tOb6PgQtqBt6K3YbSMBESLk8iYpE&callback=init";
            document.body.appendChild(script);
        }
        window.init = function() {
            var map = new BMap.Map("allmap");            // 创建Map实例
            //var point = new BMap.Point(109.18592,34.36912); // 创建点坐标
            map.centerAndZoom(new BMap.Point(120.2338341,31.58109976), 15);  // 设置中心点,地图初始化
            //map.centerAndZoom(points,20);
            map.setCurrentCity("无锡");          //设置当前城市
            map.clearOverlays();
            map.addControl(new BMap.MapTypeControl());
            map.enableScrollWheelZoom(true);                 //启用滚轮放大缩小
            map.addEventListener('click', function(e) {
                alert('点击的经纬度:' + e.latlng.lng + ', ' + e.latlng.lat);
                var mercator = map.lnglatToMercator(e.latlng.lng, e.latlng.lat);
                alert('点的墨卡托坐标:' + mercator[0] + ', ' + mercator[1]);
            });
            //向地图中添加缩放控件
            var ctrlNav = new window.BMap.NavigationControl({
                anchor: BMAP_ANCHOR_TOP_LEFT,
                type: BMAP_NAVIGATION_CONTROL_LARGE
            });
            map.addControl(ctrlNav);


    		//向地图中添加标记点
            var myIcon =new BMap.Icon("http://api.map.baidu.com/img/markers.png", new BMap.Size(23, 25), {    //小车图片
                offset: new BMap.Size(0, -5),    //相当于CSS精灵
                imageOffset: new BMap.Size(0, 0)    //图片的偏移量。为了是图片底部中心对准坐标点。
            });
    '''
    message2 = points
    message3 = markers
    message4 = overlays
    message5 = '''
            //map.setViewport(points);         //调整地图的最佳视野为显示标注数组point


        }
        loadJScript()
    </script>

    <script>
        layui.use('theme/settings/earth', layui.factory('theme/settings/earth'));
    </script>

    <!--<script type="text/javascript" src="js\jquery-2.1.1.min.js"></script>-->

    </html>
    '''

    message = message1 + '\n' + '        var points = [' + message2 + '];' + '\n        ' + message3 + '\n        ' + message4 + '\n' + message5
    return message


for i in range(2011, 2020):
    yeardata = data[data.nian == i].reset_index(drop=True)
    message = get_html(yeardata)
    filename = 'qroad' + str(i) + '.html'
    with open(filename, 'w', encoding="utf-8")as f:
        f.write(message)
        f.close()

还是简单解释一下代码吧:
前面是数据导入,数据就是我的百度地图坐标系下的经纬度坐标点。
然后是写方法,主要就是循环把点生成字符串,然后五部分加起来。
最后调用方法,生成html文件。
这样下来,文件可以秒开,给大家看下。
在这里插入图片描述
这样就算完成了,当然除了添加标记点,也还可以添加其他内容。
最后鼓励一下自己:
保持进步,保持好心情~~

猜你喜欢

转载自blog.csdn.net/u012848304/article/details/111169394