You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python+Google Static Map API获取大范围建筑级缩放地图?

问题解决指南

一、获取精确相邻的建筑级缩放地图

要实现多张地图精确衔接,核心是基于经纬度计算每张地图的中心坐标——用地名做中心无法保证精度,必须转成经纬度来控制偏移。

关键原理

Google Static Map在固定缩放级别下,每张图覆盖的经纬度范围是固定的:

  • 缩放级别zoom时,地球表面被划分为2^zoom × 2^zoom个基础瓦片(256x256像素)
  • 640x640的地图是2.5倍基础瓦片尺寸,可通过像素与经纬度的换算关系,计算出每张图的偏移量。

实操代码

import requests
import math

api_key = "YOUR_API_KEY"
base_url = "https://maps.googleapis.com/maps/api/staticmap?"

# 1. 先通过地理编码获取目标区域中心的经纬度(示例为Binche的坐标)
center_lat = 50.4938
center_lon = 4.2822
zoom = 20  # 建筑级缩放
map_size = "640x640"
label_style = "&style=feature:all|element:labels|visibility:off"

# 2. 计算当前缩放级别下,每张地图的经纬度偏移量
pixel_per_degree_lon = (2 ** zoom) * 256 / 360
pixel_per_degree_lat = (2 ** zoom) * 256 / (360 * math.cos(math.radians(center_lat)))
lon_offset = 640 / pixel_per_degree_lon  # 横向(经度)偏移
lat_offset = 640 / pixel_per_degree_lat  # 纵向(纬度)偏移

# 3. 计算覆盖100km范围所需的瓦片数量(100km≈0.9度经纬度)
target_km = 100
lon_range = target_km / 111.32  # 赤道上1度经度≈111.32km
lat_range = target_km / 111.32  # 纬度方向1度≈111km
num_tiles_lon = math.ceil(lon_range / lon_offset)
num_tiles_lat = math.ceil(lat_range / lat_offset)

# 4. 循环生成所有相邻地图
for i in range(-num_tiles_lon//2, num_tiles_lon//2 + 1):
    for j in range(-num_tiles_lat//2, num_tiles_lat//2 + 1):
        current_lat = center_lat + j * lat_offset
        current_lon = center_lon + i * lon_offset
        request_url = f"{base_url}center={current_lat:.6f},{current_lon:.6f}&zoom={zoom}&size={map_size}&key={api_key}{label_style}"
        response = requests.get(request_url)
        # 按坐标命名保存,方便后续拼接
        filename = f"Binche_zoom{zoom}_lat{current_lat:.4f}_lon{current_lon:.4f}.png"
        with open(filename, 'wb') as file:
            file.write(response.content)

二、Google Static Map API的成本评估

这个方案成本极高,完全不适合覆盖100km范围的需求:

  • 免费额度仅每月1000次请求,超出后每1000次收费约7美元
  • 缩放级别20时,每张640x640地图仅覆盖约0.03km×0.03km的区域,100km×100km的范围需要约110万次请求,总成本超过7000美元。

三、低成本/免费替代方案

1. OpenStreetMap(OSM)公开瓦片服务

完全免费,无请求次数限制(需遵守OSM使用规范:不要批量高频请求),直接获取瓦片后可拼接成大图。

import requests
import math

def latlon_to_tile(lat, lon, zoom):
    # 将经纬度转换为OSM瓦片的x、y坐标
    lat_rad = math.radians(lat)
    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

zoom = 20
center_lat = 50.4938
center_lon = 4.2822
center_x, center_y = latlon_to_tile(center_lat, center_lon, zoom)

# 按需设置需要的瓦片数量(示例取20×20片)
tile_count = 20
for x in range(center_x - tile_count//2, center_x + tile_count//2 + 1):
    for y in range(center_y - tile_count//2, center_y + tile_count//2 + 1):
        tile_url = f"https://tile.openstreetmap.org/{zoom}/{x}/{y}.png"
        response = requests.get(tile_url)
        with open(f"OSM_tile_{zoom}_{x}_{y}.png", 'wb') as file:
            file.write(response.content)

可使用PIL库将多张256x256的瓦片拼接成完整大图。

2. 本地离线渲染地图

如果需求极大,建议下载OSM离线数据(从Geofabrik获取分区数据),用Mapnik、TileMill等工具本地渲染瓦片,完全免费且不受请求限制。

3. Mapbox Static Tiles

适合商业项目,每月有50000次免费请求,超出后收费较低,逻辑与OSM类似,通过经纬度转瓦片坐标获取相邻区域。


内容的提问来源于stack exchange,提问作者Zartox29

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 02:05:34