Agent应用指南:利用GET请求获取赛力斯汽车门店位置信息

赛力斯(SERES)作为华为深度赋能的高端智能电动汽车品牌,旗下AITO问界系列凭借华为HarmonyOS智能座舱、HUAWEI ADS高阶智能驾驶及DriveONE电驱平台,构建了M5、M7、M9等覆盖中型到大型SUV的产品矩阵。在渠道策略上,赛力斯采用"授权用户中心+鸿蒙智行授权用户中心"的双轨模式,依托华为终端渠道势能与传统汽车经销商网络,快速构建全国线下触点。

目前,品牌已在全国31个省市区布局 413家门店,覆盖一线城市核心商圈及二三线城市主要汽车贸易园区,重点门店更配备"星夜服务"(18:00-21:00延时营业),形成"白天销售体验+夜间维保服务"的全时段服务闭环。这些用户中心不仅是交付终端,更是鸿蒙生态体验入口------用户可亲身体验鸿蒙座舱与华为手机、手表等设备的无缝流转,以及"一键遥控泊车"、"城市NCA"等创新智驾功能。

本文采用程序化方式解析赛力斯官方门店页面(https://auto.seres.cn/map)的服务端渲染(SSR)HTML。与传统API需多轮分页请求不同,该页面将所有门店数据预渲染在HTML中,仅需一次HTTP GET请求即可获取完整数据集。使用Python的requests库发起请求,设置User-Agent模拟浏览器,超时30秒。通过正则表达式<li\^\>*class="store-list"\^\>*>(.*?)</li>匹配每个门店区块,分别提取:<h2>中的门店名称、营业时间::\s*(.*?)</p>中的常规时段、星夜服务::\s*(.*?)</p>中的夜间时段、门店电话::\s*(.*?)</p>中的电话、门店地址::\s*(.*?)</p>中的地址,以及<span>中的服务标签。

页面未直接提供省份和城市字段,需从地址字符串反推。建立省份别名映射(如"北京"→"北京市")和城市-省份映射(如"苏州"→"江苏省"),对"肃省"等错写进行替换修复。优先从地址开头15字符匹配省份,若失败则从门店名称提取城市关键词;直辖市直接赋值。最终输出CSV(UTF-8 BOM编码)包含name、province、city、addr、phone、hours、night、tags共8个字段。共采集413条有效记录,少数未匹配的会在控制台输出以便人工校对。数据可用于门店密度统计、城市层级渗透分析、星夜服务覆盖率评估及渠道空白区域识别。

赛力斯门店查询地址:赛力斯汽车官方门店地图

打开开发者工具(F12 → Network → 刷新页面),找到第一个请求,你会发现一个map/的 HTML 响应体------这便是关键:赛力斯的门店页面采用了 Vue.js 服务端渲染(SSR),所有门店数据在服务器端就已完成渲染,以 413 个 <li class="store-list"> 标签的形式直接嵌入 HTML 源码中;

首先,我们找到网点数据的存储位置,然后看3个关键部分标头、负载、 预览;

标头:通常包括URL的连接,也就是目标资源的位置;

**负载:**对于GET请求:负载通常包含了传递的参数,有些网页负载可能为空,或者没有负载,因为所有参数都通过URL传递,这里就没有负载;

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

门店 HTML 结构解析

接下来,我们开始解析 HTML 结构,获取具体数据,在 HTML 中,每家门店是一个独立的 <li class="store-list"> 块,结构如下:

python 复制代码
<li class="store-list">
  <h2>AITO授权用户中心•北京姚家园</h2>
  <div class="type-list"><span>星夜服务</span></div>
  <p>营业时间:08:30-17:30</p>
  <p>星夜服务:18:00-21:00</p>
  <p>门店电话:010-51332233</p>
  <p>门店地址:北京市朝阳区朝阳北路63号</p>
</li>

提取规则:

HTML 标签/内容 匹配方式 对应字段
<h2>...</h2> 正则提取标签内容 门店名称
营业时间:... 正则 营业时间[::](.*?)</p> 营业时间
星夜服务:... 正则 星夜服务[::](.*?)</p> 星夜服务时间
门店电话:... 正则 门店电话[::](.*?)</p> 联系电话
门店地址:... 正则 门店地址[::](.*?)</p> 门店地址
<span>星夜服务</span> 正则提取 span 内容 服务标签

注意: 页面并未直接提供省份和城市字段,需要从"门店地址"字符串中通过省市区关键词匹配反推。此外,地址中存在少量非标准写法(如"苏州吴中经济开发区"缺少"市"字、"肃省天水市"实为"甘肃省天水市"),需要在解析逻辑中做容错处理。

方法思路

整体流程分为三步,且仅需一次 HTTP 请求:

  1. 获取页面 HTML:用 requests.get() 直接拉取 赛力斯汽车 的完整 HTML 响应;
  2. 正则提取门店块:匹配所有 <li class="store-list"> 标签,逐块解析字段;
  3. 地址反推省市区:从"门店地址"字符串中匹配省份和城市关键词,映射为标准行政区划名称。

**第一步:**利用requests库发送HTTP请求获取所有门店信息,并根据标签进行保存,另存为csv;

完整代码#运行环境 Python 3.11

python 复制代码
import csv
import os
import re
import requests

resp = requests.get('https://auto.seres.cn/map',
                    headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'},
                    timeout=30)
resp.encoding = 'utf-8'
html = resp.text

pattern = r'<li[^>]*class="store-list"[^>]*>(.*?)</li>'
blocks = re.findall(pattern, html, re.DOTALL)

PROVINCE_ALIASES = {
    '北京市': ['北京'], '天津市': ['天津'], '河北省': ['河北'], '山西省': ['山西'],
    '内蒙古自治区': ['内蒙古'], '辽宁省': ['辽宁'], '吉林省': ['吉林'],
    '黑龙江省': ['黑龙江'], '上海市': ['上海'], '江苏省': ['江苏'],
    '浙江省': ['浙江'], '安徽省': ['安徽'], '福建省': ['福建'],
    '江西省': ['江西'], '山东省': ['山东'], '河南省': ['河南'],
    '湖北省': ['湖北'], '湖南省': ['湖南'], '广东省': ['广东'],
    '广西壮族自治区': ['广西'], '海南省': ['海南'], '重庆市': ['重庆'],
    '四川省': ['四川'], '贵州省': ['贵州'], '云南省': ['云南'],
    '西藏自治区': ['西藏'], '陕西省': ['陕西'], '甘肃省': ['甘肃'],
    '青海省': ['青海'], '宁夏回族自治区': ['宁夏'],
    '新疆维吾尔自治区': ['新疆'],
}

# City to province mapping
CITY_PROVINCE = {
    '东莞市': '广东省', '中山市': '广东省', '佛山市': '广东省', '珠海市': '广东省',
    '深圳市': '广东省', '广州市': '广东省', '惠州市': '广东省', '汕头市': '广东省',
    '厦门市': '福建省', '福州市': '福建省', '泉州市': '福建省',
    '南宁市': '广西壮族自治区', '桂林市': '广西壮族自治区', '柳州市': '广西壮族自治区',
    '杭州市': '浙江省', '宁波市': '浙江省', '温州市': '浙江省', '嘉兴市': '浙江省',
    '苏州市': '江苏省', '南京市': '江苏省', '无锡市': '江苏省', '常州市': '江苏省',
    '扬州市': '江苏省', '徐州市': '江苏省', '南通市': '江苏省', '盐城市': '江苏省',
    '武汉市': '湖北省', '宜昌市': '湖北省', '襄阳市': '湖北省',
    '成都市': '四川省', '绵阳市': '四川省', '德阳市': '四川省',
    '长沙市': '湖南省', '株洲市': '湖南省', '湘潭市': '湖南省',
    '济南市': '山东省', '青岛市': '山东省', '烟台市': '山东省', '淄博市': '山东省',
    '潍坊市': '山东省', '临沂市': '山东省', '济宁市': '山东省',
    '郑州市': '河南省', '洛阳市': '河南省', '开封市': '河南省', '新乡市': '河南省',
    '西安市': '陕西省', '咸阳市': '陕西省', '宝鸡市': '陕西省',
    '昆明市': '云南省', '曲靖市': '云南省', '大理市': '云南省',
    '贵阳市': '贵州省', '遵义市': '贵州省',
    '合肥市': '安徽省', '芜湖市': '安徽省', '蚌埠市': '安徽省',
    '南昌市': '江西省', '九江市': '江西省',
    '沈阳市': '辽宁省', '大连市': '辽宁省',
    '长春市': '吉林省', '吉林市': '吉林省',
    '哈尔滨市': '黑龙江省', '大庆市': '黑龙江省',
    '太原市': '山西省', '大同市': '山西省',
    '兰州市': '甘肃省',
    '西宁市': '青海省',
    '银川市': '宁夏回族自治区',
    '乌鲁木齐市': '新疆维吾尔自治区',
    '呼和浩特市': '内蒙古自治区', '包头市': '内蒙古自治区',
    '拉萨市': '西藏自治区',
    '海口市': '海南省', '三亚市': '海南省',
    '石家庄市': '河北省', '唐山市': '河北省', '保定市': '河北省', '邯郸市': '河北省',
    # Other cities
    '六盘水市': '贵州省', '都匀市': '贵州省', '黔南布依族苗族自治州': '贵州省',
    '安阳市': '河南省', '许昌市': '河南省', '南阳市': '河南省', '平顶山市': '河南省',
    '随州市': '湖北省', '黄石市': '湖北省', '荆州市': '湖北省',
    '岳阳市': '湖南省', '益阳市': '湖南省',
    '赣州市': '江西省',
    '常熟市': '江苏省', '昆山市': '江苏省',
    '温岭市': '浙江省', '乐清市': '浙江省', '长兴县': '浙江省',
    '宜宾市': '四川省', '泸州市': '四川省', '攀枝花市': '四川省',
    '克拉玛依市': '新疆维吾尔自治区', '库尔勒市': '新疆维吾尔自治区',
    # More cities
    '泰州市': '江苏省', '宿迁市': '江苏省', '肇庆市': '广东省', '六安市': '安徽省',
    '信阳市': '河南省', '邵阳市': '湖南省', '商丘市': '河南省', '娄底市': '湖南省',
    '威海市': '山东省', '滨州市': '山东省', '自贡市': '四川省', '承德市': '河北省',
    '驻马店市': '河南省', '舟山市': '浙江省', '周口市': '河南省', '通化市': '吉林省',
    '秦皇岛市': '河北省', '运城市': '山西省', '临汾市': '山西省', '茂名市': '广东省',
    '渭南市': '陕西省', '绍兴市': '浙江省', '台州市': '浙江省', '金华市': '浙江省',
    '湖州市': '浙江省', '衢州市': '浙江省', '丽水市': '浙江省',
    '德州市': '山东省', '聊城市': '山东省', '菏泽市': '山东省', '日照市': '山东省',
    '镇江市': '江苏省', '连云港市': '江苏省', '淮安市': '江苏省',
    '十堰市': '湖北省', '孝感市': '湖北省', '荆门市': '湖北省', '鄂州市': '湖北省',
    '郴州市': '湖南省', '永州市': '湖南省', '怀化市': '湖南省',
    '河源市': '广东省', '清远市': '广东省', '韶关市': '广东省', '梅州市': '广东省',
    '揭阳市': '广东省', '潮州市': '广东省', '湛江市': '广东省', '云浮市': '广东省',
    '漳州市': '福建省', '宁德市': '福建省', '莆田市': '福建省', '龙岩市': '福建省',
    '保定市': '河北省', '张家口市': '河北省', '沧州市': '河北省', '廊坊市': '河北省',
    '衡水市': '河北省', '邢台市': '河北省',
    '晋城市': '山西省', '长治市': '山西省', '朔州市': '山西省', '晋中市': '山西省',
    '锦州市': '辽宁省', '鞍山市': '辽宁省', '抚顺市': '辽宁省', '营口市': '辽宁省',
    '盘锦市': '辽宁省', '朝阳市': '辽宁省', '丹东市': '辽宁省',
    '四平市': '吉林省', '延边朝鲜族自治州': '吉林省',
    '鹤岗市': '黑龙江省', '牡丹江市': '黑龙江省', '绥化市': '黑龙江省',
    '漯河市': '河南省', '濮阳市': '河南省', '三门峡市': '河南省',
    '宜春市': '江西省', '景德镇市': '江西省', '上饶市': '江西省',
    '德阳市': '四川省', '南充市': '四川省', '遂宁市': '四川省', '乐山市': '四川省',
    '眉山市': '四川省', '广安市': '四川省', '达州市': '四川省',
    '毕节市': '贵州省', '安顺市': '贵州省', '黔东南苗族侗族自治州': '贵州省',
    '玉溪市': '云南省', '红河哈尼族彝族自治州': '云南省',
    '汉中市': '陕西省', '延安市': '陕西省', '榆林市': '陕西省',
    '白银市': '甘肃省', '天水市': '甘肃省', '酒泉市': '甘肃省',
    '海东市': '青海省', '海西蒙古族藏族自治州': '青海省',
    '喀什地区': '新疆维吾尔自治区', '巴音郭楞蒙古自治州': '新疆维吾尔自治区',
}


def extract_province_city(addr, name_hint=''):
    if not addr:
        return '', ''

    # Fix common typos
    addr = addr.replace('肃省', '甘肃省')

    province = ''
    city = ''

    # 1. Try province alias
    for full, aliases in PROVINCE_ALIASES.items():
        for a in aliases:
            idx = addr.find(a)
            if idx >= 0 and idx < 15:
                province = full
                break
        if province:
            break

    # 2. Try city-to-province mapping (with and without 市 suffix)
    if not province:
        for city_name, prov in CITY_PROVINCE.items():
            if addr.startswith(city_name):
                province = prov
                city = city_name
                break
            # Try without 市/州/区 suffix
            base = re.sub(r'[市州县区盟]$', '', city_name)
            if len(base) >= 2 and (addr.startswith(base) or base in addr[:10]):
                province = prov
                city = city_name
                break

    # 3. Try from store name (e.g., "AITO授权用户中心•北京姚家园")
    if not province and name_hint:
        for full, aliases in PROVINCE_ALIASES.items():
            for a in aliases:
                if a in name_hint:
                    province = full
                    break
            if province:
                break

    # 4. Extract city from address (only if province is known)
    if province and not city:
        rest = addr
        for a in PROVINCE_ALIASES.get(province, []):
            idx = rest.find(a)
            if idx >= 0:
                rest = rest[idx + len(a):]
                break
        pattern_city = r'([\u4e00-\u9fff]{2,4}(?:市|地区|州|盟|县))'
        pattern_auto_region = r'([\u4e00-\u9fff]{4,8}(?:自治州|自治县))'
        m = re.match(pattern_city, rest)
        if not m:
            m = re.match(pattern_auto_region, rest)
        if m:
            city = m.group(1)
        elif province in ['北京市', '天津市', '上海市', '重庆市']:
            city = province

    if province in ['北京市', '天津市', '上海市', '重庆市']:
        city = province

    return province, city


stores = []
for block in blocks:
    s = {}
    nm = re.search(r'<h2[^>]*>(.*?)</h2>', block)
    store_name = ''
    if nm:
        store_name = re.sub(r'<[^>]+>', '', nm.group(1)).strip()
        s['name'] = store_name

    tag_spans = re.findall(r'<span[^>]*>(.*?)</span>', block)
    tags = [t.strip() for t in tag_spans if t.strip() and len(t.strip()) < 20 and t.strip()]
    s['tags'] = '|'.join(tags)

    for label, key in [('营业时间', 'hours'), ('星夜服务', 'night'), ('门店电话', 'phone'), ('门店地址', 'addr')]:
        m = re.search(rf'{label}[::]\s*(.*?)</p>', block)
        s[key] = re.sub(r'<[^>]+>', '', m.group(1)).strip() if m else ''

    province, city = extract_province_city(s.get('addr', ''), store_name)
    s['province'] = province
    s['city'] = city

    stores.append(s)

# Save CSV directly in current directory
csv_path = 'SERES_store_data.csv'
with open(csv_path, 'w', newline='', encoding='utf-8-sig') as f:
    writer = csv.DictWriter(f, fieldnames=['name', 'province', 'city', 'addr', 'phone', 'hours', 'night', 'tags'])
    writer.writeheader()
    writer.writerows(stores)

empty = [s for s in stores if not s['province']]
prov_count = {}
for s in stores:
    p = s.get('province', '?')
    prov_count[p] = prov_count.get(p, 0) + 1

# Print summary in Chinese
total = len(stores)
unmatched = len(empty)
print(f"成功提取 {total} 家门店信息,其中 {unmatched} 家未能识别省份。")

if unmatched > 0:
    print("以下门店未匹配到省份(可检查地址或补充映射):")
    for s in empty:
        print(f"  {s['name'][:60]} | {s['addr'][:80]}")

数据会以csv表格的形式,保存在运行脚本的目录下,表格名:SERES_store_data.csv;

数据字段说明:

字段 示例 说明
name AITO授权用户中心•北京姚家园 门店全称
province 北京市 省级行政区(标准名称)
city 北京市 地级市/区
addr 北京市朝阳区朝阳北路63号 详细地址
phone 010-51332233 联系电话
hours 08:30-17:30 常规营业时间
night 18:00-21:00 星夜服务时间(空=不支持)
tags 星夜服务 服务标签

第二步: 坐标系转换,由于赛力斯门店数据使用的是高德坐标系(GCJ-02),为了在ArcGIS上准确展示而不发生偏移,我们需要将门店的坐标从GCJ-02转换为WGS-84坐标系。我们可以利用coord-convert库中的gcj2wgs(lng, lat)函数,也可以用免费这个网站:批量转换工具:地理编码 (高德) 地址转经纬度 - 批量工具网

对CSV文件中的门店坐标列进行转换,完成坐标转换后,再将数据导入ArcGIS进行可视化;

接下来,我们基于采集到的413家门店数据,我们从空间分布、城市层级渗透、战略缺口三个维度进行分析。

第一段:空间分布特征

赛力斯门店呈现显著的"东部密集、西部稀疏、沿海优先"格局。TOP 5 省份------广东省(45家)、浙江省(34家)、江苏省(26家)、山东省(22家)、四川省(18家)------合计占比超过35%,与智己汽车的"东密西疏"分布高度相似。但赛力斯的差异化在于:中西部省份(贵州14家、云南11家、新疆6家)的渗透率明显高于同期的智己,这与华为终端渠道在三四线城市的既有网络深度密切相关------AITO门店多依托于华为授权体验店的选址逻辑,天然具备更广的触达半径。

第二段:城市层级渗透情况

从城市能级看:一线城市(北上广深)门店约40+家,以"鸿蒙智行授权用户中心"旗舰店为主,兼具销售、交付、售后全功能;新一线及省会城市(如杭州、成都、武汉、长沙)单城普遍3-5家;普通地级市(如遵义、都匀、邵阳、信阳)已出现1-2家门店覆盖,部分县级市(诸暨、乐清、温岭)亦有布局。值得注意的是,新疆克拉玛依、库尔勒,青海西宁,宁夏银川等西北边远城市均已设立门店------赛力斯的渠道下沉速度和广度在当前新能源品牌中处于领先梯队。

第三段:星夜服务覆盖分析

413家门店中,超半数支持"星夜服务"(延时营业至21:00),这一比例显著高于行业平均水平。星夜服务门店的地域分布与整体门店分布基本一致,但在一线城市和新一线城市的核心商圈门店中覆盖率更高------说明品牌将延时服务作为差异化竞争手段,重点服务于高净值用户的晚间看车、试驾和维保需求。不过,部分中西部门店的星夜服务标注存在信息缺失,可能是数据录入问题而非实际不提供,建议在数据分析时加以区分。

第四段:战略缺口与机会

当前明显空白和薄弱区域包括:

  • 东北地区:吉林(6家)、辽宁(10家)、黑龙江(7家),三省合计23家,不足广东一省数量,且集中在沈阳、大连、长春、哈尔滨四城,地级市几乎空白;
  • 西北内陆:宁夏仅1家、青海2家、甘肃3家、西藏1家------这些省份的新能源渗透率本身较低,但充电基建正在快速改善,是潜在的下沉机会;
  • 港澳台地区:页面显示"香港特别行政区"、"澳门特别行政区"、"台湾省"选项但当前无实际门店数据,国际化拓展尚未启动。

文章仅用于分享个人学习成果与个人存档之用,分享知识,如有侵权,请联系作者进行删除。所有信息均基于作者的个人理解和经验,不代表任何官方立场或权威解读。

相关推荐
花月C2 小时前
Agent上下文三级压缩
python·prompt·ai编程
专注搞钱2 小时前
用Python写了个SPC自动分析工具,效率提升10倍
开发语言·python
yijianace2 小时前
Python爬虫实战:ThreadPoolExecutor多线程采集书籍信息与图片下载
开发语言·爬虫·python
郝亚军2 小时前
win11安装python3.12.7和pycharm
ide·python·pycharm
资深流水灯工程师2 小时前
PyCharm 虚拟环境完整配置指南(PySide6 开发专用)
ide·python·pycharm
宸津-代码粉碎机2 小时前
Spring AI企业级实战|Agent长期记忆持久化落地,彻底解决多轮对话上下文丢失问题
java·开发语言·人工智能·后端·python·spring
在放️2 小时前
Python 爬虫 · bs4 模块基础
开发语言·爬虫·python
belong_my_offer2 小时前
Python 数据采集完全指南 —— 从零开始掌握网络爬虫与文件读取
开发语言·爬虫·python
stephon_1002 小时前
国产大模型 Agent 开发实战:用 milu 5 分钟搭一个多用户 AI Agent 服务(DeepSeek/Qwen/Kimi/GLM)
人工智能·python·ai·chatgpt