李二爷 發表於 2026-1-9 09:43:28

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

<p>在内网环境中开发,无法使用高德在线瓦片服务,需要下载到本地或者部署到内网服务器中进行使用,如何下载离线瓦片呢,可以使用python脚本进行</p>
<p>以下是完整代码</p>
<div class="jb51code"><pre class="brush:py;">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&amp;size=1&amp;scale=1&amp;style=8&amp;x={x}&amp;y={y}&amp;z={z}
      # 卫星底图:http://webst0{1-4}.is.autonavi.com/appmaptile?style=6&amp;x={x}&amp;y={y}&amp;z={z}
      self.tile_url_template = "http://webrd0{server}.is.autonavi.com/appmaptile?lang=zh_cn&amp;size=1&amp;scale=1&amp;style=8&amp;x={x}&amp;y={y}&amp;z={z}"
      # 服务节点(避免单节点请求频繁被限制)
      self.servers =
      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} - {self.zoom_range}")

      for z in range(self.zoom_range, self.zoom_range + 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 += 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)</pre></div>
<p>以上测试代码下载的是北京市中心偏南部的核心区域离线瓦片服务</p>
<p>具体结构如下图所示:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010909431427.png" /></p>
<p><strong>如何验证离线瓦片是否可用呢?</strong></p>
<p>可以快速创建一个html文件,使用leafle 引入./amap_tiles/{z}/{x}/{y}.png下载的离线瓦片快速实现一个基础地图展示,代码如下</p>
<div class="jb51code"><pre class="brush:xhtml;">&lt;!DOCTYPE html&gt;
&lt;html lang="zh-CN"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;title&gt;Leaflet加载高德离线瓦片&lt;/title&gt;
    &lt;!-- 引入Leaflet的CSS和JS(在线CDN) --&gt;
    &lt;link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" rel="external nofollow"/&gt;
    &lt;script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"&gt;&lt;/script&gt;
    &lt;!-- 引入高德坐标系适配插件(解决偏移问题) --&gt;
    &lt;script src="https://unpkg.com/leaflet.gridlayer.ChinaProvider@1.0.2/dist/leaflet.ChineseTmsProviders.js"&gt;&lt;/script&gt;
    &lt;style&gt;
      /* 让地图占满整个页面 */
      #map {
            width: 100vw;
            height: 100vh;
            margin: 0;
            padding: 0;
      }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div id="map"&gt;&lt;/div&gt;

    &lt;script&gt;
      // 1. 初始化地图(中心点设为你下载的区域,这里是北京)
      var map = L.map('map', {
            // 禁用地图缩放超出瓦片范围
            minZoom: 1,
            maxZoom: 10,// 对应你下载的最大缩放级别
            zoomControl: true// 显示缩放控件
      }).setView(, 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);
    &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</pre></div>
<p>在本地服务中运行html文件:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010909431491.png" /></p>
頁: [1]
查看完整版本: python脚本实现下载高德离线底图瓦片并使用