在LBS应用开发中,"地址转经纬度"是最常见的需求之一。外卖配送、共享单车、车辆调度,都需要把用户输入的文字地址转换为可计算的坐标。

本文从技术实现角度,对比国内主流的三个地理编码服务——高德地图、百度地图、丰图,涵盖接口调用、返回格式、免费额度、适用场景,帮助开发者在项目选型时做出判断。

一、地理编码的技术原理

地理编码(Geocoding)是将结构化或自由文本地址转换为地理坐标的过程。核心流程三步:

1. 地址分词与标准化:把"北京市朝阳区望京SOHO T1 5层"拆解为省/市/区/街道/门牌号

2. 地址匹配:在POI数据库中检索最相似的记录

3. 坐标输出:返回匹配结果的经纬度坐标

不同厂商的POI数据库覆盖范围、匹配算法、更新频率不同,同一个地址在不同平台返回的结果可能存在差异。选API本质上是选POI数据库和匹配策略。

二、接口基本信息对比

对比项

丰图

高德地图

百度地图

接口地址

https://gis-apis.sf-express.com/all/api/geocode/geo

https://restapi.amap.com/v3/geocode/geo

http://api.map.baidu.com/geocoding/v3/

请求方式

GET

GET

GET

认证方式

API Key(Header)

Key(参数)

AK(参数)

坐标系

GCJ-02 / BD-09 可选

GCJ-02

BD-09

免费额度对比

平台

免费额度

超量定价

备注

丰图

首月1000次

单接口购买,无最低消费

适合初期验证

高德

50,000次/月

约¥0.005元/次

需企业认证

百度

5,000次/日

约¥0.02元/次

个人认证即可

返回字段对比

字段

丰图

高德

百度

坐标

xcoord, ycoord

location(合并字符串)

location.lng, location.lat

行政区划

adcode

adcode

置信度

confidence(0-1)

confidence(0-100)

精确度判断

precise(0/1)

标准化地址

standardization

formatted_address

三个平台的返回格式差异不小,集成时需要注意:

status类型不一致:丰图/百度返回数字0表示成功,高德返回字符串"1"

坐标格式不同:高德返回合并字符串"lng,lat",丰图和百度返回独立字段

坐标系不同:丰图/高德默认GCJ-02,百度使用BD-09,混用会偏移几十米

三、Python调用实现

丰图地理编码

// python
import requests

def fengtu_geocode(address: str, city: str = None, coord_type: int = 1):
    """
    丰图地理编码API
    官方文档: https://lbs.sfmap.com.cn/

    Args:
        address: 详细地址(必填)
        city: 城市名(可选)
        coord_type: 1=GCJ-02, 2=BD-09
    """
    url = "https://gis-apis.sf-express.com/all/api/geocode/geo"
    params = {"address": address, "cc": coord_type}
    if city:
        params["city"] = city

    try:
        resp = requests.get(url, params=params, timeout=10)
        result = resp.json()
        if result.get("status") == 0:  # 数字0表示成功
            data = result["result"]
            return {
                "success": True,
                "lng": data.get("xcoord"),
                "lat": data.get("ycoord"),
                "adcode": data.get("adcode"),
                "confidence": data.get("confidence"),
                "standardized_address": data.get("standardization")
            }
        return {"success": False, "error": f"API错误: {result}"}
    except Exception as e:
        return {"success": False, "error": str(e)}

result = fengtu_geocode("深圳市南山区科技中三路5号", city="深圳")

高德地理编码

// python
import requests

def amap_geocode(address: str, key: str, city: str = None):
    """
    高德地理编码API
    官方文档: https://lbs.amap.com/api/webservice/guide/api/georegeo

    Args:
        address: 详细地址(必填)
        key: 高德Web服务API密钥(必填)
        city: 城市名(可选)
    """
    url = "https://restapi.amap.com/v3/geocode/geo"
    params = {"key": key, "address": address}
    if city:
        params["city"] = city

    try:
        resp = requests.get(url, params=params, timeout=10)
        result = resp.json()
        if result.get("status") == "1" and result.get("geocodes"):  # 字符串"1"
            data = result["geocodes"][0]
            lng, lat = data["location"].split(",")
            return {
                "success": True,
                "lng": float(lng),
                "lat": float(lat),
                "adcode": data.get("adcode"),
                "formatted_address": data.get("formatted_address"),
                "level": data.get("level")
            }
        return {"success": False, "error": f"未找到匹配: {result}"}
    except Exception as e:
        return {"success": False, "error": str(e)}

result = amap_geocode("北京市朝阳区望京SOHO", "your_amap_key")

百度地理编码

// python
import requests

def baidu_geocode(address: str, ak: str, city: str = None):
    """
    百度地理编码API v3
    官方文档: https://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding

    Args:
        address: 详细地址(必填)
        ak: 百度地图API密钥(必填)
        city: 城市名(可选)
    """
    url = "http://api.map.baidu.com/geocoding/v3/"
    params = {"ak": ak, "address": address, "output": "json"}
    if city:
        params["city"] = city

    try:
        resp = requests.get(url, params=params, timeout=10)
        result = resp.json()
        if result.get("status") == 0:  # 数字0表示成功
            data = result["result"]
            return {
                "success": True,
                "lng": data["location"]["lng"],
                "lat": data["location"]["lat"],
                "precise": data.get("precise"),
                "confidence": data.get("confidence"),
                "level": data.get("level")
            }
        return {"success": False, "error": f"API错误: {result}"}
    except Exception as e:
        return {"success": False, "error": str(e)}

result = baidu_geocode("上海市浦东新区陆家嘴环路1000号", "your_baidu_ak")

集成多个地理编码API时,这几个坑容易踩到:

1. status类型陷

丰图和百度的成功状态是数字0,高德是字符串"1"。写统一判断逻辑时,if result.get("status") == 0在高德那边永远False。建议统一转字符串处理:

// python
def is_success(result):
    status = result.get("status")
    return str(status) in ["0", "1"]

2. 坐标系混用偏移

GCJ-02和BD-09之间相差几十米。如果你的底图是高德的(GCJ-02),却用了百度API返回的BD-09坐标,标记点会偏移。丰图的cc参数可以指定输出坐标系,其他平台需要手动转换。

3. 高德location字段是合并字符串

高德返回"113.931756,22.543201",需要split(",")拆分,容易忘记。

四、场景选型建议

场景

推荐方案

核心理由

物流配送/末端揽收

丰图

末端精度高、置信度反馈、地址标准化

通用互联网应用

高德

POI覆盖广、免费额度高、生态成熟

需要精确度判断

百度

precise字段直接标识是否精确到门牌

已有百度技术栈

百度

产品联动无缝

业务验证期

高德/百度

免费额度充足

选型没有标准答案,关键是别拿通用方案硬套物流场景。物流行业的地址有特殊性——格式不标准(城中村缩写、自建楼编号)、行政区划敏感(区县边界模糊)、调用量大(日均几十万次起),通用地图API在这些点上往往差一口气。

建议先用各平台的免费额度做功能验证,确认满足需求后再根据实际调用量做成本测算。做好异常降级和日志记录,不要只依赖一家API。

备注:本文数据来源于各平台官方API文档,核验时间2026年5月。定价信息以各平台官网最新公告为准。

更多推荐