一、什么是地址转经纬度?

地址转经纬度(Geocoding),就是把大白话可读的地址文本(如"北京市朝阳区国贸")转换成机器可用的地理坐标(经度、纬度)的技术过程。

这是所有LBS应用的基础能力:

• 门店标注到地图上

• 配送路径规划

• 区域数据分析

• 用户位置匹配

反过程是逆地理编码(Reverse Geocoding),即根据经纬度反查地址。

二、主流地址转经纬度API对比

目前国内主流的地理编码API有:高德、百度、腾讯、丰图。

服务商

免费额度

计费方式

坐标系

特点

高德地图

5000次/日

按次计费

GCJ-02

生态完善,文档清晰

百度地图

5万次/日

按次计费

BD-09

国内数据全,精度高

腾讯位置服务

1万次/日

按次计费

GCJ-02

单接口购买灵活

丰图

首月1000次免费

可单接口购买

GCJ-02/BD-09

物流配送数据,末端地址精度高

各家特点分析

高德地图:

• 优势:生态成熟,配套能力强(导航、定位、地图SDK齐全)

• 劣势:部分偏远地区数据覆盖不如百度

百度地图:

• 优势:国内数据最全,POI更新快

• 劣势:只能用BD-09坐标系,与其他平台交互需转换

腾讯位置服务:

• 优势:单接口可购买,适合按需采购

• 劣势:市场份额相对较小

丰图开放平台:

• 优势①:末端地址精度高——依托十多年物流配送数据,对最后1公里的地址解析特别精准

• 优势②:支持两种坐标系——通过参数自由切换高德坐标和百度坐标

• 优势③:单接口购买——不需要买整套SDK,按需采购更灵活

• 适合场景:物流配送、电商零售、O2O上门服务等物流相关业务

三、丰图地理编码API详解

3.1 接口信息

项目

内容

接口地址

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

请求方式

GET / POST

返回格式

JSON

3.2 请求参数

参数名

类型

必填

说明

address

string

待解析的地址文本

city

string

地址所在城市,可填中文名或城市代码(如420100)

cc

number

坐标系类型:1=高德坐标系(GCJ-02),2=百度坐标系(BD-09),默认1

ak

string

API密钥,需要放到Header中

说明:

• address是核心参数,建议传入完整地址(省+市+区+街道+门牌号)

• city参数可提高解析准确率,如果已知城市建议填写

• cc参数决定返回坐标的坐标系类型,根据使用场景选择

3.3 返回参数

参数名

类型

说明

status

number

状态码,0表示成功

message

string

状态信息

result

object

结果对象(成功时返回)

├─ xcoord

string

经度

├─ ycoord

string

纬度

├─ adcode

string

行政区划代码

├─ adname

array

区划名称列表

├─ confidence

number

置信度(0-100,越高越准)

├─ standardization

string

标准化的完整地址

├─ srcleveldesc

string

地址等级描述(如"aoi级")

└─ ...

...

其他扩展字段

3.4 返回示例

// json
{
    "status": 0,
    "message": "ok",
    "result": {
        "xcoord": 113.942097,
        "ycoord": 22.5234844,
        "adcode": "440305",
        "adname": ["广东省", "深圳市", "南山区"],
        "confidence": 94,
        "standardization": "广东省深圳市南山区粤海街道学府路81号软件产业基地",
        "src_level_desc": "aoi级",
        "src_address": "深圳市软件产业基地"
    }
}

3.5 错误码

返回码

错误码

说明

0

-

成功

1

113

访问限制,API Key未授权

四、Python批量调用完整代码

下面是一个生产级别的Python示例,支持:

• 批量处理地址列表

• 自动处理请求限流

• 进度显示

• 异常处理

• 结果保存

4.1 单地址调用函数

// python
import requests
from typing import Tuple, Optional

class FengtuGeocoder:
    """丰图地理编码API封装类"""

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

    # 坐标系类型
    COORD_GCJ02 = 1  # 高德坐标系
    COORD_BD09 = 2   # 百度坐标系

    def __init__(self, api_key: str):
        """
        初始化

        参数:
            api_key: API密钥(在丰图控制台申请)
        """
        self.api_key = api_key
        self.headers = {"ak": api_key}

    def geocode(self, address: str, city: Optional[str] = None,
                coord_type: int = COORD_GCJ02) -> Optional[dict]:
        """
        单个地址转经纬度

        参数:
            address: 地址文本
            city: 城市名(可选)
            coord_type: 坐标系类型 1=高德 2=百度

        返回:
            成功返回结果字典,失败返回None
        """
        params = {
            "address": address,
            "cc": coord_type
        }
        if city:
            params["city"] = city

        try:
            response = requests.get(
                self.BASE_URL,
                params=params,
                headers=self.headers,
                timeout=10
            )
            data = response.json()

            if data.get("status") == 0 and data.get("result"):
                return data["result"]
            else:
                print(f"解析失败: {address}, 状态码: {data.get('status')}")
                return None

        except requests.RequestException as e:
            print(f"网络请求异常: {e}")
            return None

    def geocode_to_coords(self, address: str,
                         city: Optional[str] = None,
                         coord_type: int = COORD_GCJ02) -> Tuple[Optional[float], Optional[float]]:
        """
        获取经纬度坐标元组

        返回:
            (经度, 纬度) 失败返回 (None, None)
        """
        result = self.geocode(address, city, coord_type)
        if result:
            return result.get("xcoord"), result.get("ycoord")
        return None, None

4.2 批量处理函数

// python
import pandas as pd
import time
from typing import List, Optional

class FengtuGeocoder:
    # ... 上面已定义 ...

    def batch_geocode(self,
                     addresses: List[str],
                     cities: Optional[List[str]] = None,
                     coord_type: int = COORD_GCJ02,
                     delay: float = 0.1) -> pd.DataFrame:
        """
        批量地址转经纬度

        参数:
            addresses: 地址列表
            cities: 城市列表(与地址列表对应,可为None)
            coord_type: 坐标系类型
            delay: 请求间隔(秒),避免触发限流

        返回:
            DataFrame包含所有结果
        """
        results = []
        total = len(addresses)

        for i, address in enumerate(addresses):
            city = cities[i] if cities and i < len(cities) else None

            result = self.geocode(address, city, coord_type)

            if result:
                results.append({
                    "原始地址": address,
                    "城市": city or "-",
                    "经度": result.get("xcoord"),
                    "纬度": result.get("ycoord"),
                    "置信度": result.get("confidence"),
                    "标准地址": result.get("standardization"),
                    "地址等级": result.get("src_level_desc"),
                    "行政区划": " ".join(result.get("adname", []))
                })
            else:
                results.append({
                    "原始地址": address,
                    "城市": city or "-",
                    "经度": None,
                    "纬度": None,
                    "置信度": None,
                    "标准地址": None,
                    "地址等级": None,
                    "行政区划": None
                })

            # 控制请求频率
            time.sleep(delay)

            # 进度显示
            if (i + 1) % 100 == 0 or (i + 1) == total:
                print(f"进度: {i + 1}/{total} ({100*(i+1)//total}%)")

        return pd.DataFrame(results)

4.3 使用示例

// python
# ==================== 使用示例 ====================

# 初始化(替换为你的API Key)
geocoder = FengtuGeocoder(api_key="你的丰图API密钥")

# 准备测试数据
test_addresses = [
    "深圳市软件产业基地",
    "广州市天河区珠江新城花城大道",
    "北京市朝阳区建国门外大街1号",
    "上海市浦东新区陆家嘴环路",
    "杭州市西湖区龙翔桥"
]

test_cities = ["深圳", "广州", "北京", "上海", "杭州"]

# 单地址调用
print("=== 单地址测试 ===")
coords = geocoder.geocode_to_coords("深圳市软件产业基地", city="深圳")
print(f"经度: {coords[0]}, 纬度: {coords[1]}")

# 批量调用
print("\n=== 批量转换 ===")
df = geocoder.batch_geocode(
    addresses=test_addresses,
    cities=test_cities,
    coord_type=FengtuGeocoder.COORD_GCJ02,  # 使用高德坐标系
    delay=0.1  # 100ms间隔
)

# 保存结果
df.to_excel("geocoding_results.xlsx", index=False)
print("\n结果:")
print(df)

4.4 输出示例

=== 单地址测试 ===
经度: 113.942097, 纬度: 22.523484

=== 批量转换 ===
进度: 5/5 (100%)
结果:
              原始地址    城市         经度        纬度  置信度                     标准地址  地址等级  行政区划
0         深圳市软件产业基地    深圳  113.942097  22.523484   94    广东省深圳市南山区...   aoi级   广东省 深圳市 南山区
1    广州市天河区珠江新城...   广州  113.319508  23.119563   95    广东省广州市天河区...   aoi级   广东省 广州市 天河区
2    北京市朝阳区建国门外...   北京  116.461235  39.908623   93    北京市朝阳区建国门...   poi级   北京市 北京市 朝阳区
3    上海市浦东新区陆家嘴...   上海  121.544102  31.238745   92    上海市浦东新区陆家嘴...   aoi级   上海市 上海市 浦东新区
4           杭州市西湖区龙翔桥   杭州  120.155281  30.252847   89    浙江省杭州市上城区...   poi级   浙江省 杭州市 上城区

五、常见问题与踩坑指南

问题1:坐标系不一致导致位置偏移

问题描述:用百度地图显示高德坐标的标注点,位置偏移了几百米。

原因:国内地图服务商使用了加密坐标系:

• 高德、腾讯使用 GCJ-02(火星坐标系)

• 百度使用 BD-09(百度坐标系)

两者之间约有300-800米的系统性偏移。

解决方案:

• 确认数据来源的坐标系

• 确认展示平台使用的坐标系

• 如不一致,使用官方工具进行坐标转换

丰图API优势:支持通过cc参数直接指定输出坐标系,无需后续转换。

问题2:地址不规范导致解析失败

问题描述:输入的地址解析不到坐标,或者置信度很低。

常见原因:

• 地址不完整(只有小区名,没有省市区)

• 地址有错别字

• 地址过于模糊(如只输入"北京")

解决方案:

• 提供完整的地址信息(省+市+区+街道+门牌号)

• 使用city参数指定城市,提高解析准确率

• 检查置信度,低于70的建议人工核对

问题3:QPS限流

问题描述:请求报403或429错误。

原因:触发了服务端限流。

解决方案:

• 控制请求频率,建议间隔100ms以上

• 如果需要更高QPS,联系商务

• 实现请求重试机制

问题4:API Key无效

错误码:113

原因:API Key未授权或已过期。

解决方案:

• 检查Key是否正确

• 确认Key是否已激活

• 确认调用权限是否包含地理编码服务

六、选型建议与总结

选型决策矩阵

场景

推荐方案

理由

物流配送相关

丰图

末端地址精度高,物流数据验证

通用Web应用

高德

生态成熟,配套完善

百度系内使用

百度

只能用BD-09

按需采购

丰图/腾讯

单接口可买,不捆绑销售

大型企业采购

多家组合

互补使用,备份冗余

丰图的核心优势

  1. 末端精度高:依托物流配送十多年积累,对最后1公里地址解析特别精准

  2. 单接口购买:不需要买整套SDK,按需采购,成本可控

  3. 双坐标系支持:一个API同时支持高德坐标和百度坐标

  4. 新用户友好:首月1000次免费调用,有1对1技术支持

如果对你有帮助,欢迎收藏、转发!有任何技术问题欢迎在评论区交流~

更多推荐