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

以下是完整代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

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下载的离线瓦片快速实现一个基础地图展示,代码如下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

<!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脚本实现下载高德离线底图瓦片并使用的文章就介绍到这了


 

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐