【Folium】使用离线地图

发布于:2025-05-14 ⋅ 阅读:(16) ⋅ 点赞:(0)

相关文献

离线地图下载

我们使用 Offline Map Maker 进行地图下载。

特别注意:Folium 默认支持 WGS84 坐标系,建议下载 WGS84 坐标系的地图(比如高德、谷歌等),而类似百度地图(BD09 坐标系)默认不支持。

在这里插入图片描述

由于此软件收费较贵,也可以通过如下链接下载(注意网站是否允许爬虫)。

[!TIP]

Gaode base map with areas roads labels buildings (China)

http://wprd01.is.autonavi.com/appmaptile?lang=zh_cn&style=7&ltype=7&scl=0&size=0&x=417&y=222&z=9

import glob
import shutil
import math
import os
import requests
from concurrent.futures import ThreadPoolExecutor, as_completed


# 下载单个URL的函数
def download_url(url, filename):
    try:
        print(f"开始下载: {url}")
        response = requests.get(url, timeout=10)
        with open(filename, 'wb') as f:
            f.write(response.content)
        print(f"下载完成: {url} -> 保存为 {filename}")
        return url, True
    except Exception as e:
        print(f"下载失败: {url}, 错误: {e}")
        return url, False


def save_file_with_directories(file_path, content):
    """
    自动创建路径中的所有目录,并保存文件内容。

    :param file_path: 文件路径,例如 'a/b/c.png'
    :param content: 要写入的内容(二进制或文本)
    """
    # 获取文件所在目录
    directory = os.path.dirname(file_path)

    # 如果目录不为空,则创建目录(exist_ok=True 表示目录存在也不会报错)
    if directory:
        os.makedirs(directory, exist_ok=True)

    # 写入文件(以二进制方式为例)
    with open(file_path, 'wb') as f:
        f.write(content)


# 多线程下载器
def multi_thread_download(urls, filenames, output_dir='downloads', max_workers=5):
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    futures = []
    results = []

    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        for i, (url, filename) in enumerate(zip(urls, filenames)):
            filename = os.path.join(output_dir, filename)
            future = executor.submit(download_url, url, filename)
            futures.append(future)

        for future in as_completed(futures):
            result = future.result()
            results.append(result)

    return results


def deg2num(lat_deg, lon_deg, zoom):
    """
    根据给定的纬度、经度和缩放级别计算瓦片的X和Y坐标。

    参数:
        lat_deg (float): 纬度
        lon_deg (float): 经度
        zoom (int): 缩放级别

    返回:
        tuple: 包含X和Y坐标的元组
    """
    lat_rad = math.radians(lat_deg)
    n = 2.0 ** zoom
    xtile = int((lon_deg + 180.0) / 360.0 * n)
    ytile = int((1.0 - math.asinh(math.tan(lat_rad)) / math.pi) / 2.0 * n)
    return (xtile, ytile)


def move_file(src_file, dest_file):
    """
    将文件移动到指定路径,如果路径不存在则自动创建。

    :param src_file: 源文件路径(需要移动的文件)
    :param dest_file: 目标文件夹路径
    """
    # 获取源文件的文件名
    filename = os.path.basename(src_file)

    # 获取文件所在目录
    directory = os.path.dirname(dest_file)

    # 如果目录不为空,则创建目录(exist_ok=True 表示目录存在也不会报错)
    if directory:
        os.makedirs(directory, exist_ok=True)

    # 移动文件
    shutil.move(src_file, dest_file)
    print(f"文件已从 '{src_file}' 移动至 '{dest_file}'")


# 示例用法
if __name__ == "__main__":
    left_lon = 113 + 52 / 60
    right_lon = 114 + 18 / 60
    top_lat = 22 + 35 / 60
    bottom_lat = 22 + 8 / 60
    from_zoom = 9
    to_zoom = 18

    i = 0
    url_list = []
    filenames = []
    for zoom in range(from_zoom, to_zoom + 1):
        x_min, y_min = deg2num(top_lat, left_lon, zoom)
        x_max, y_max = deg2num(bottom_lat, right_lon, zoom)
        for x in range(x_min, x_max + 1):
            for y in range(y_min, y_max + 1):
                filename = f"{zoom}_{x}_{y}.png"
                url = f"http://wprd0{i + 1}.is.autonavi.com/appmaptile?lang=zh_cn&style=7&ltype=7&scl=0&size=0&x={x}&y={y}&z={zoom}"  # 高德地图
                url_list.append(url)
                filenames.append(filename)
                i = (i + 1) % 4

    # 开始多线程下载
    multi_thread_download(url_list, filenames, max_workers=8)

    for source_file in glob.glob("downloads/*.png"):
        filename = os.path.basename(source_file)
        zoom, x, y = filename[:-4].split("_")
        target_folder = f"{zoom}/{x}/{y}.png"
        move_file(source_file, target_folder)

Folium 使用离线地图

import folium


offline_map_path = 'D:/offlinemaps/Gaode base map with areas roads labels buildings (China)/{z}/{x}/{y}.png'  # 离线地图文件路径

# 创建一个以香港为中心的地图,zoom_start参数控制初始缩放级别
m = folium.Map(
    location=[22.5, 114],
    zoom_start=9,
    tiles=offline_map_path,
    attr='Gaode base map with areas roads labels buildings (China)'
)

# 在地图上添加一个标记,默认的标记类型是'Marker'
folium.Marker(
    location=[22.5, 114],  # 标记的位置坐标
    popup='这里是香港',  # 点击标记时显示的信息
    icon=folium.Icon(color='blue')  # 标记的颜色
).add_to(m)

# 将地图保存为HTML文件
m.save('hk_map.html')

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到