python脚本实现下载高德离线底图瓦片并使用

 更新时间:2026年01月09日 09:43:28   作者:沉默璇年  
在内网环境中开发,无法使用高德在线瓦片服务,需要下载到本地或者部署到内网服务器中进行使用,下面我们就来看看如何使用python脚本下载高德离线底图瓦片并使用吧

在内网环境中开发,无法使用高德在线瓦片服务,需要下载到本地或者部署到内网服务器中进行使用,如何下载离线瓦片呢,可以使用python脚本进行

以下是完整代码

import math  # 新增这行,导入math模块
import requests
import os
from PIL import Image
from urllib.parse import quote
import time

# 高德瓦片下载配置
class AmapTileDownloader:
    def __init__(self, save_path='amap_tiles', zoom_range=(1, 18)):
        """
        初始化下载器
        :param save_path: 瓦片保存根路径
        :param zoom_range: 缩放级别范围(高德瓦片缩放级1-18)
        """
        self.save_path = save_path
        self.zoom_range = zoom_range
        # 高德瓦片服务地址(矢量底图,可替换为卫星图)
        # 矢量底图:http://webrd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}
        # 卫星底图:http://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}
        self.tile_url_template = "http://webrd0{server}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}"
        # 服务节点(避免单节点请求频繁被限制)
        self.servers = [1, 2, 3, 4]
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
        }

    def mercator2tile(self, lon, lat, zoom):
        """
        经纬度转瓦片坐标(墨卡托投影)
        :param lon: 经度
        :param lat: 纬度
        :param zoom: 缩放级别
        :return: x, y 瓦片坐标
        """
        lat_rad = lat * 3.141592653589793 / 180.0
        n = 2.0 ** zoom
        x = int((lon + 180.0) / 360.0 * n)
        y = int((1.0 - (math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad)))) / math.pi) / 2.0 * n)
        return x, y

    def download_tile(self, x, y, z, server=1):
        """
        下载单个瓦片
        :param x: 瓦片x坐标
        :param y: 瓦片y坐标
        :param z: 缩放级别
        :param server: 服务节点(1-4)
        :return: 是否下载成功
        """
        # 拼接瓦片URL
        tile_url = self.tile_url_template.format(server=server, x=x, y=y, z=z)
        # 构建保存路径:根路径/缩放级别/x坐标/y坐标.png
        tile_save_path = os.path.join(self.save_path, str(z), str(x))
        os.makedirs(tile_save_path, exist_ok=True)
        tile_file = os.path.join(tile_save_path, f"{y}.png")

        # 避免重复下载
        if os.path.exists(tile_file):
            print(f"瓦片 {z}/{x}/{y} 已存在,跳过")
            return True

        try:
            # 发送请求(添加超时和重试)
            response = requests.get(tile_url, headers=self.headers, timeout=10)
            response.raise_for_status()  # 抛出HTTP错误

            # 保存瓦片
            with open(tile_file, 'wb') as f:
                f.write(response.content)

            # 校验图片是否有效
            try:
                img = Image.open(tile_file)
                img.verify()
                print(f"成功下载:{z}/{x}/{y}")
                return True
            except:
                os.remove(tile_file)
                print(f"瓦片无效,已删除:{z}/{x}/{y}")
                return False

        except Exception as e:
            print(f"下载失败 {z}/{x}/{y}:{str(e)}")
            return False

    def download_area(self, min_lon, min_lat, max_lon, max_lat):
        """
        下载指定经纬度范围的瓦片
        :param min_lon: 最小经度
        :param max_lon: 最大经度
        :param min_lat: 最小纬度
        :param max_lat: 最大纬度
        """
        import math  # 延迟导入,避免初始化时依赖
        print(f"开始下载范围:[{min_lon},{min_lat}] - [{max_lon},{max_lat}]")
        print(f"缩放级别范围:{self.zoom_range[0]} - {self.zoom_range[1]}")

        for z in range(self.zoom_range[0], self.zoom_range[1] + 1):
            # 计算范围对应的瓦片坐标
            min_x, min_y = self.mercator2tile(min_lon, max_lat, z)  # 注意lat反转
            max_x, max_y = self.mercator2tile(max_lon, min_lat, z)

            print(f"\n缩放级别 {z}:瓦片范围 x[{min_x}-{max_x}], y[{min_y}-{max_y}]")
            server_idx = 0  # 轮询服务节点

            # 遍历所有瓦片坐标
            for x in range(min_x, max_x + 1):
                for y in range(min_y, max_y + 1):
                    # 轮询服务节点
                    server = self.servers[server_idx % len(self.servers)]
                    server_idx += 1

                    # 下载瓦片(添加小延迟,避免请求过快被限制)
                    self.download_tile(x, y, z, server)
                    time.sleep(0.1)  # 可根据实际情况调整

        print("\n所有瓦片下载完成!")

# ------------------- 示例使用 -------------------
if __name__ == "__main__":
    # 初始化下载器:保存路径+缩放级别(建议先测试1-10级,级别越高瓦片越多)
    downloader = AmapTileDownloader(save_path='amap_tiles', zoom_range=(1, 10))

    # 下载指定区域(示例:北京市中心经纬度范围,可替换为自己需要的区域)
    # 经纬度可从高德地图拾取:https://lbs.amap.com/console/show/picker
    min_lon, min_lat = 116.30, 39.80  # 左下角经纬度
    max_lon, max_lat = 116.50, 40.00  # 右上角经纬度
    downloader.download_area(min_lon, min_lat, max_lon, max_lat)

以上测试代码下载的是北京市中心偏南部的核心区域离线瓦片服务

具体结构如下图所示:

如何验证离线瓦片是否可用呢?

可以快速创建一个html文件,使用leafle 引入./amap_tiles/{z}/{x}/{y}.png下载的离线瓦片快速实现一个基础地图展示,代码如下

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Leaflet加载高德离线瓦片</title>
    <!-- 引入Leaflet的CSS和JS(在线CDN) -->
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" rel="external nofollow"  />
    <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
    <!-- 引入高德坐标系适配插件(解决偏移问题) -->
    <script src="https://unpkg.com/leaflet.gridlayer.ChinaProvider@1.0.2/dist/leaflet.ChineseTmsProviders.js"></script>
    <style>
        /* 让地图占满整个页面 */
        #map {
            width: 100vw;
            height: 100vh;
            margin: 0;
            padding: 0;
        }
    </style>
</head>
<body>
    <div id="map"></div>

    <script>
        // 1. 初始化地图(中心点设为你下载的区域,这里是北京)
        var map = L.map('map', {
            // 禁用地图缩放超出瓦片范围
            minZoom: 1,
            maxZoom: 10,  // 对应你下载的最大缩放级别
            zoomControl: true  // 显示缩放控件
        }).setView([39.908823, 116.397470], 8);  // 中心点经纬度+初始缩放级别

        // 2. 加载本地高德离线瓦片
        L.tileLayer('./amap_tiles/{z}/{x}/{y}.png', {  // 对应瓦片目录结构
            attribution: '高德离线瓦片',  // 地图版权说明
            tileSize: 256,  // 高德瓦片默认尺寸256x256
            noWrap: true,   // 禁止地图水平循环
            // 瓦片加载失败时显示的占位图
            errorTileUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAIElEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg=='
        }).addTo(map);

        // 可选:添加比例尺控件
        L.control.scale({
            imperial: false,  // 不显示英制单位
            maxWidth: 200
        }).addTo(map);
    </script>
</body>
</html>

在本地服务中运行html文件:

到此这篇关于python脚本实现下载高德离线底图瓦片并使用的文章就介绍到这了,更多相关python下载高德离线瓦片内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解如何在pyqt中通过OpenCV实现对窗口的透视变换

    详解如何在pyqt中通过OpenCV实现对窗口的透视变换

    这篇文章主要介绍了如何在pyqt中通过OpenCV实现对窗口的透视变换,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • 用python搭建一个花卉识别系统

    用python搭建一个花卉识别系统

    这学期修了一门机器视觉的选修课,课设要是弄一个花卉识别的神经网络,所以我网上找了开源代码进行了修改,最后成功跑起来,结果只有一个准确率(94%)既然都跑了这个神经网络的代码,那么干脆就把这个神经网络真正的使用起来,把这个神经网络弄成一个可视化界面
    2021-06-06
  • python批量生成本地ip地址的方法

    python批量生成本地ip地址的方法

    这篇文章主要介绍了python批量生成本地ip地址的方法,实例分析了Python实现生成本地IP地址并绑定到网卡上的技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-03-03
  • Python 对输入的数字进行排序的方法

    Python 对输入的数字进行排序的方法

    今天小编就为大家分享一篇Python 对输入的数字进行排序的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-06-06
  • PyCharm接入DeepSeek实现AI编程的操作流程

    PyCharm接入DeepSeek实现AI编程的操作流程

    DeepSeek 是一家专注于人工智能技术研发的公司,致力于开发高性能、低成本的 AI 模型,接下来,我们把DeepSeek接入到PyCharm中,并利用其能力辅助我们进行代码开发,感兴趣的小伙伴跟着小编一起来看看吧
    2025-01-01
  • Python+OpenCV人脸检测原理及示例详解

    Python+OpenCV人脸检测原理及示例详解

    这篇文章主要为大家详细介绍了Python+OpenCV人脸检测原理及示例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-12-12
  • python tkinter制作用户登录界面的简单实现

    python tkinter制作用户登录界面的简单实现

    这篇文章主要介绍了python tkinter制作用户登录界面的简单实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Django框架 查询Extra功能实现解析

    Django框架 查询Extra功能实现解析

    这篇文章主要介绍了Django框架 查询Extra功能实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • pygame库pgu使用示例代码

    pygame库pgu使用示例代码

    pgu全称是Phil’s pyGame Utilities,是pygame的一组模块与脚本,其中还有gui集成了一些小模块,现在用pygame制作小游戏的人越来越多,但是pygame它是没有弹窗机制的,今天通过本文给大家介绍pygame库pgu使用示例代码,需要的朋友参考下吧
    2021-08-08
  • Django发送邮件和itsdangerous模块的配合使用解析

    Django发送邮件和itsdangerous模块的配合使用解析

    这篇文章主要介绍了Django发送邮件和itsdangerous模块的配合使用解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-08-08

最新评论