【Folium】使用离线地图

[复制链接]
发表于 2025-9-1 23:33:13 | 显示全部楼层 |阅读模式
相关文献



  • Folium — Folium 0.19.5 documentation
  • Offline Map Maker
离线地图下载

我们使用 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
  1. import glob
  2. import shutil
  3. import math
  4. import os
  5. import requests
  6. from concurrent.futures import ThreadPoolExecutor, as_completed
  7. # 下载单个URL的函数
  8. def download_url(url, filename):
  9.     try:
  10.         print(f"开始下载: {url}")
  11.         response = requests.get(url, timeout=10)
  12.         with open(filename, 'wb') as f:
  13.             f.write(response.content)
  14.         print(f"下载完成: {url} -> 保存为 {filename}")
  15.         return url, True
  16.     except Exception as e:
  17.         print(f"下载失败: {url}, 错误: {e}")
  18.         return url, False
  19. def save_file_with_directories(file_path, content):
  20.     """
  21.     自动创建路径中的所有目录,并保存文件内容。
  22.     :param file_path: 文件路径,例如 'a/b/c.png'
  23.     :param content: 要写入的内容(二进制或文本)
  24.     """
  25.     # 获取文件所在目录
  26.     directory = os.path.dirname(file_path)
  27.     # 如果目录不为空,则创建目录(exist_ok=True 表示目录存在也不会报错)
  28.     if directory:
  29.         os.makedirs(directory, exist_ok=True)
  30.     # 写入文件(以二进制方式为例)
  31.     with open(file_path, 'wb') as f:
  32.         f.write(content)
  33. # 多线程下载器
  34. def multi_thread_download(urls, filenames, output_dir='downloads', max_workers=5):
  35.     if not os.path.exists(output_dir):
  36.         os.makedirs(output_dir)
  37.     futures = []
  38.     results = []
  39.     with ThreadPoolExecutor(max_workers=max_workers) as executor:
  40.         for i, (url, filename) in enumerate(zip(urls, filenames)):
  41.             filename = os.path.join(output_dir, filename)
  42.             future = executor.submit(download_url, url, filename)
  43.             futures.append(future)
  44.         for future in as_completed(futures):
  45.             result = future.result()
  46.             results.append(result)
  47.     return results
  48. def deg2num(lat_deg, lon_deg, zoom):
  49.     """
  50.     根据给定的纬度、经度和缩放级别计算瓦片的X和Y坐标。
  51.     参数:
  52.         lat_deg (float): 纬度
  53.         lon_deg (float): 经度
  54.         zoom (int): 缩放级别
  55.     返回:
  56.         tuple: 包含X和Y坐标的元组
  57.     """
  58.     lat_rad = math.radians(lat_deg)
  59.     n = 2.0 ** zoom
  60.     xtile = int((lon_deg + 180.0) / 360.0 * n)
  61.     ytile = int((1.0 - math.asinh(math.tan(lat_rad)) / math.pi) / 2.0 * n)
  62.     return (xtile, ytile)
  63. def move_file(src_file, dest_file):
  64.     """
  65.     将文件移动到指定路径,如果路径不存在则自动创建。
  66.     :param src_file: 源文件路径(需要移动的文件)
  67.     :param dest_file: 目标文件夹路径
  68.     """
  69.     # 获取源文件的文件名
  70.     filename = os.path.basename(src_file)
  71.     # 获取文件所在目录
  72.     directory = os.path.dirname(dest_file)
  73.     # 如果目录不为空,则创建目录(exist_ok=True 表示目录存在也不会报错)
  74.     if directory:
  75.         os.makedirs(directory, exist_ok=True)
  76.     # 移动文件
  77.     shutil.move(src_file, dest_file)
  78.     print(f"文件已从 '{src_file}' 移动至 '{dest_file}'")
  79. # 示例用法
  80. if __name__ == "__main__":
  81.     left_lon = 113 + 52 / 60
  82.     right_lon = 114 + 18 / 60
  83.     top_lat = 22 + 35 / 60
  84.     bottom_lat = 22 + 8 / 60
  85.     from_zoom = 9
  86.     to_zoom = 18
  87.     i = 0
  88.     url_list = []
  89.     filenames = []
  90.     for zoom in range(from_zoom, to_zoom + 1):
  91.         x_min, y_min = deg2num(top_lat, left_lon, zoom)
  92.         x_max, y_max = deg2num(bottom_lat, right_lon, zoom)
  93.         for x in range(x_min, x_max + 1):
  94.             for y in range(y_min, y_max + 1):
  95.                 filename = f"{zoom}_{x}_{y}.png"
  96.                 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}"  # 高德地图
  97.                 url_list.append(url)
  98.                 filenames.append(filename)
  99.                 i = (i + 1) % 4
  100.     # 开始多线程下载
  101.     multi_thread_download(url_list, filenames, max_workers=8)
  102.     for source_file in glob.glob("downloads/*.png"):
  103.         filename = os.path.basename(source_file)
  104.         zoom, x, y = filename[:-4].split("_")
  105.         target_folder = f"{zoom}/{x}/{y}.png"
  106.         move_file(source_file, target_folder)
复制代码
Folium 使用离线地图

  1. import folium
  2. offline_map_path = 'D:/offlinemaps/Gaode base map with areas roads labels buildings (China)/{z}/{x}/{y}.png'  # 离线地图文件路径
  3. # 创建一个以香港为中心的地图,zoom_start参数控制初始缩放级别
  4. m = folium.Map(
  5.     location=[22.5, 114],
  6.     zoom_start=9,
  7.     tiles=offline_map_path,
  8.     attr='Gaode base map with areas roads labels buildings (China)'
  9. )
  10. # 在地图上添加一个标记,默认的标记类型是'Marker'
  11. folium.Marker(
  12.     location=[22.5, 114],  # 标记的位置坐标
  13.     popup='这里是香港',  # 点击标记时显示的信息
  14.     icon=folium.Icon(color='blue')  # 标记的颜色
  15. ).add_to(m)
  16. # 将地图保存为HTML文件
  17. m.save('hk_map.html')
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

×
登录参与点评抽奖,加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表