📌 为什么是春风动力?
如果你关注摩托车圈,CFMOTO 春风动力这个名字不会陌生。
这家 1989 年诞生于浙江杭州的企业,如今已是中国最大的全地形车出口商和国产中大排量摩托车的头部玩家。从 450SR 仿赛到 800MT 探险车,从四轮 ATV 到 ZEEHO 极核电动两轮------春风的产品矩阵正在以前所未有的速度扩张。
但一个品牌能否真正"走进"消费者,不仅看产品,更要看渠道:
门店是品牌与用户之间最短的距离。
截至 2026 年 6 月,CFMOTO 在中国大陆布局了超过 700 家授权门店 ,覆盖从一线城市到县域市场的广阔版图。这些门店分为 Lite(基础店) 、Prime(高级店) 和 Flagship(旗舰店) 三个等级,承担着销售、售后、品牌展示等多重角色。
那么问题来了:春风动力到底在全国开了多少家店?哪些省份布局最密?Prime 门店集中在哪些城市?
官网虽然提供了 门店查询页面,但只支持按当前位置查看附近门店,无法俯瞰全局。
于是,我决定自己动手,把全国所有门店数据"挖"出来。
🔍 找到那只"下蛋的母鸡"
打开官方门店查询网址,按 F12 打开开发者工具 → 切换到 Network(网络) 面板 → 刷新页面 → 筛选 Fetch/XHR 请求。
地区选择这里选择"全部地区";

首先,我们找到门店数据的存储位置,然后看3个关键部分标头、负载、 预览;
标头:通常包括URL的连接,也就是目标资源的位置;

负载:对于POST请求:负载通常包含了传递的参数,因为所有参数都通过URL传递,这里我们可以看到查询关键词city(所在城市)、lon,lat(经纬度坐标)、distinct(距离)等等参数,但是选择全部地区的话,这里全部为空;

预览:指的是对响应内容的快速查看或摘要显示,可以帮助用户快速了解返回的数据结构或内容片段,我们可以看到数据在data里;

再看 Preview(响应预览):
json
{
"data": [
{
"storeNo": "0000105167-01",
"storeName": "CFMOTO春风动力(银川金凤店)",
"dealerName": "宁夏银友服务有限公司",
"province": "宁夏回族自治区",
"city": "银川市",
"district": "金凤区",
"fullAddress": "宁夏省银川市金凤区长城中路388-9号",
"phone": "17811113039",
"workTime": "夏季:08:30-19:00\n冬季:08:30-18:00",
"longitude": 106.232807,
"latitude": 38.465602,
"operationalLevel": "Lite",
"isSale": 1,
"isService": 1,
...
}
],
"meta": {
"count": 59,
"filters": { "ip": "223.166.104.73" }
}
}
数据结构非常完整------店名、地址、经纬度、电话、等级、销售/服务标签......应有尽有。
🧩 一个参数,打开全国版图
方法思路
1.找到对应数据存储位置,获取门店标签数据以及对应标签内容;
2.我们通过requests库发送HTTP请求,来遍历全国网点的标签数据;
3.地理编码→地址转经纬度,再通过coord-convert库实现BD09转WGS84;
第一步:利用requests库发送HTTP请求对应数据标签并获取所有门店数据,并根据标签进行保存,另存为csv;
完整代码#运行环境 Python 3.11
python
# -*- coding: utf-8 -*-
import json
import csv
import urllib.request
import ssl
import os
BASE_URL = "https://cn.cfmoto.com"
OUTPUT_DIR = os.path.dirname(os.path.abspath(__file__))
CSV_FILE = os.path.join(OUTPUT_DIR, "cfmoto_stores.csv")
REQUEST_BODY = {
"province": "",
"city": "",
"district": "",
"keyword": "",
"state": 1,
"latitude": "",
"longitude": "",
"radius": "",
}
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Content-Type": "application/json",
"Referer": "https://cn.cfmoto.com/dealer-locator",
}
CSV_COLUMNS = [
"storeNo", "storeName", "dealerName",
"province", "city", "district",
"fullAddress", "phone", "workTime",
"longitude", "latitude",
"operationalLevel", "grade", "saleGrade",
"isSale", "isService",
"areaTotal", "areaHall", "areaService",
"isCFBrand", "isKTMBrand", "isATVBrand",
"isZHBrand", "isCATVBrand", "isOCCBrand",
"dealerNo", "state", "modifyTime", "openDate",
"provinceCode", "cityCode", "districtCode",
]
def main():
url = f"{BASE_URL}/api/store-locator/stores"
data = json.dumps(REQUEST_BODY).encode("utf-8")
req = urllib.request.Request(url, data=data, headers=HEADERS, method="POST")
with urllib.request.urlopen(req, timeout=60, context=ssl.create_default_context()) as r:
response = json.loads(r.read().decode("utf-8"))
stores = response.get("data", [])
print(f"成功获取 {len(stores)} 家 CFMOTO 春风动力门店数据,并已保存至 CSV 文件。")
if stores:
with open(CSV_FILE, "w", newline="", encoding="utf-8-sig") as f:
writer = csv.DictWriter(f, fieldnames=CSV_COLUMNS, extrasaction="ignore")
writer.writeheader()
writer.writerows(stores)
if __name__ == "__main__":
main()
数据会以csv表格的形式,保存在运行脚本的目录下,表格名:cfmoto_stores.csv;(注:文中数据截至 2026 年 6 月)
数据标签包括:storeNo(门店id)、storeName(门店名称)、 fullAddress(门店地址)、phone(电话)、worktime(工作时间)、lon&lat(坐标)、operationalLevel(服务类型),其他一些非关键标签,这里省略;

第二步:坐标系转换,由于门店数据使用的是高德坐标系(GCJ-02)和百度坐标系(BD-09),这里为了方便转换,以高德坐标系为准,为了在ArcGIS上准确展示而不发生偏移,我们需要将门店的坐标从GCJ-02转换为WGS-84坐标系。我们可以利用coord-convert库中的gcj2wgs(lng, lat)函数,也可以用免费这个网站:批量转换工具: https://piliang.cc0.top/geocoding-amap;
这里如果没办法从地图上知道用的什么坐标系可以,从这个网站进行查询验证: http://jingweidu.757dy.com/;

📊 数据全貌:733 家门店背后的渠道版图
空间分布:一只沿东海岸展开的翅膀 🦅
| 排名 | 省份 | 门店数 | 特征 |
|---|---|---|---|
| 🥇 | 广东省 | 60 | 消费大省,摩托车文化浓厚 |
| 🥈 | 江苏省 | 59 | 长三角核心腹地 |
| 🥉 | 浙江省 | 55 | 春风动力大本营所在 |
| 4 | 四川省 | 55 | 西南市场绝对重镇 |
| 5 | 河南省 | 43 | 人口大省,渠道下沉典范 |
| 6 | 山东省 | 40 | 北方最大摩托车消费市场 |
| 7 | 湖南省 | 39 | 中部崛起代表 |
| 8 | 贵州省 | 39 | 山地骑行需求旺盛 |
| 9 | 云南省 | 38 | 摩旅天堂,门店加密中 |
| 10 | 安徽省 | 31 | 长三角辐射区域 |
🔍 洞察一:"东密西疏"的梯度格局
门店分布呈现清晰的沿海→中部→西部 三级梯度。TOP 5 省份(粤苏浙川豫)合计 272 家,占全国总量的 37.1%。这与中国摩托车消费的核心市场高度吻合------经济发达的沿海省份和地形复杂的西南山区是两大增长极。
值得注意的是,西藏仅 2 家、青海仅 2 家 。这些地区的春风车主在售后维保方面面临不小的挑战,也意味着空白市场蕴含的机会。
等级结构:一个"金字塔"正在长高 📐
| 等级 | 数量 | 占比 | 定位 |
|---|---|---|---|
| 🥉 Lite(基础店) | 460 | 62.8% | 销售+基础服务,快速铺量 |
| 🥈 Prime(高级店) | 271 | 37.0% | 全功能旗舰体验,品牌形象担当 |
| 🥇 Flagship(旗舰店) | 2 | 0.3% | 品牌制高点(仅北京、杭州) |
🔍 洞察二:Lite 是扩张的"步兵",Prime 是升级的"信号"
460 家 Lite 店构成了春风渠道的"毛细血管",承担着下沉市场覆盖的使命------尤其是在三四线城市和县域市场。而 271 家 Prime 店则集中在省会和经济发达城市,提供从试驾体验到售后服务的一站式场景。
想想看:当你骑着一辆春风 800MT 穿越 G318 进藏,沿途能在成都找到 Prime 旗舰服务,在西昌也有 Lite 店做应急维修------这个"Prime 做纵深、Lite 做覆盖"的双轨体系,正是春风从"卖车"到"养用户"战略转型的物理载体。
服务深度:每三家店就有一家能修车 🔧
| 类型 | 数量 | 占比 |
|---|---|---|
| 销售 + 服务 | 332 | 45.3% |
| 仅销售 | 389 | 53.1% |
| 仅服务 | 12 | 1.6% |
🔍 洞察三:近半数门店具备售后服务能力
对于摩托车品牌而言,售后服务网络的密度直接决定了用户"敢不敢骑远"。45.3% 的"销服一体"门店比例说明:春风正在有意识地把销售网络升级为服务网络------这比单纯的门店数量增长更能体现品牌的服务深度。
🗺️ 进阶玩法:将门店数据转化为在线可视化看板
拿到这 733 条带经纬度的结构化门店数据后,最直观的呈现方式莫过于将其部署为一个在线的交互式地图看板。通过浏览器即可访问,无需安装任何 GIS 软件,适合快速分享给团队或用于日常数据查阅。
如果你不想从零搭建前端页面,可以直接使用配套的 HTML 看板文件(已集成 Leaflet 地图、MarkerCluster 聚合标记、Chart.js 统计图表及多维度筛选功能),并通过 GitHub Pages 一键部署,生成一个在线可访问、可交互的全国门店分布地图。
春风动力全国摩托车门店HTML网页: 春风动力全国门店分布地图
GitHub Pages 部署步骤(零成本、无需服务器)
1. 注册 GitHub 账号
访问 github.com 注册账号(如已有账号可跳过)。
2. 创建新仓库(Repository)
点击页面右上角的 + → New repository,填写仓库名称(如 cfmoto-map),选择 Public(公开仓库),勾选 Add a README file,然后点击 Create repository。
3. 上传 HTML 看板文件
进入新创建的仓库,点击 Add file → Upload files,将你的 HTML 文件(如 index.html)拖拽到上传区域,然后在页面底部点击 Commit changes 提交。
建议将主文件命名为
index.html,这样访问仓库地址时可直接显示地图页面,无需额外输入文件名。
4. 启用 Pages 服务
进入仓库 Settings → 左侧菜单找到 Pages(通常在 Code and automation 分类下)。在 Branch 下拉框中选择 main 分支,目录保持 / (root),点击 Save。
5. 获取在线访问地址
保存后等待 1-2 分钟,页面刷新后会显示一行提示:
Your site is published at https://<你的用户名>.github.io/<仓库名>/
点击该链接即可在线访问你的门店地图看板。
6. 后续更新数据
如需更新门店数据,只需在本地替换 HTML 文件中的数据部分,重新上传覆盖原文件即可,GitHub Pages 会自动重新部署,通常在 1 分钟内生效。
文章仅用于分享个人学习成果与个人存档之用,分享知识,如有侵权,请联系作者进行删除。所有信息均基于作者的个人理解和经验,不代表任何官方立场或权威解读。