HTML应用指南:利用GET请求获取全国一加授权零售店位置信息

发布于:2025-08-12 ⋅ 阅读:(21) ⋅ 点赞:(0)

一加授权零售店作为深受科技爱好者青睐的数码产品服务终端,自品牌创立以来,始终致力于为用户提供高品质的产品体验与专业贴心的客户服务。凭借简约科技感的空间设计与全面的售前咨询、售后支持服务,一加授权零售店不仅是手机及智能生态产品的展示与销售平台,更成为用户了解新品技术、体验智能生活、获取使用指导的重要互动空间。

本文将探讨如何通过发送 GET 请求,从一加中国官方网站获取一加授权零售店的分布信息,并展示使用 Python 中 requests 库发起请求的方法,从而提取各城市的详细门店地址、营业时间、联系方式等关键数据。通过对 API 返回的 JSON 数据进行解析,最终可整理出结构化的门店列表信息。

这些数据不仅有助于全面了解一加授权零售店在全国范围内的市场覆盖趋势与区域布局特征,还能为消费者提供高效的门店查询服务,进一步提升购机、维修、系统升级与咨询服务的便利性。结合不同城市的门店密度、选址特点(如核心商圈、大型购物中心)以及周边消费环境进行分析,还可以洞察各地用户在产品偏好与服务需求上的差异。

这对于一加未来在中国市场的渠道拓展策略优化、新店选址评估以及本地化服务能力升级都具有重要的参考价值。通过对门店数据的系统收集与深入分析,不仅能够支持品牌的科学决策,也有助于推动客户体验的持续提升,从而更好地满足中国消费者日益多样化和个性化的需求。

一加授权零售店门店地址:一加授权零售店

我们第一步先找到门店数据的存储位置,然后看3个关键部分标头、负载、 预览;

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

负载:对于GET请求:负载通常包含了传递的参数,有些网页负载可能为空,或者没有负载,因为所有参数都通过URL传递,这里我们可以看到城市编码,当前页数,还是明文,没有进行加密;

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

接下来就是数据获取部分,先讲一下方法思路,一共三个步骤;

方法思路

  1. 找到对应数据存储位置,获取所有店铺列表的相关标签数据;
  2. 我们通过获取和改变行政区编码,来遍历全国门店数据;
  3. 地理编码转换,再通过coord-convert库实现GCJ-02转WGS84;

第一步:我们先找到对应数据存储位置,获取所有门店列表,经过测试,这里可以选择"省"进行筛选,再选择"市",每个区域会生成一个html,我们通过修改行政区编码来进行数据获取,为了方便我们可以建立一个包含市级行政区​​​​编码的字典,通过遍历行政区板面来查询全国数据;

这里我们发现,一加授权零售店网页对行政区的编码是自成体系的,所以我们要获取市一级所有的id;

🎯 目标:提取所有“市级”行政区(地级市/直辖市下辖区市)

想要的是:所有“市”这一级的单位,即:

  • 普通省份下的地级市(如:南宁市、兰州市、淄博市、福州市);
  • 直辖市本身(如:重庆市、上海市)—— 它们在系统中也作为“市”级存在;

但注意:

  • "重庆"是省级(pid=7757),不是我们要的"市";
  • "重庆市"是市级(pid=7758),是我们要的;
  • "上海市"等其他直辖市,同理;

完整代码#运行环境 Python 3.11

import requests
import csv

# 配置
URL = "https://opsiteapi-cn.oneplus.com/api/public/v1/store/getDistrictsByCode"
PARAMS = {"code": "cn"}
HEADERS = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
    "Accept": "application/json",
    "Referer": "https://www.oneplus.com/cn/store"
}

# 获取区域数据
try:
    print("正在获取区域数据...")
    response = requests.get(URL, params=PARAMS, headers=HEADERS, timeout=10)
    response.raise_for_status()
    data = response.json()

    if data.get("code") != "0":
        raise Exception(f"接口错误: {data.get('msg', '未知')}")

    districts = data["data"]["districts"]
except Exception as e:
    print(f"数据获取失败: {e}")
    exit()

# 提取市级单位(父级为省)
provinces = {d["id"] for d in districts if d.get("pid") == 7757}
cities = [
    {"id": d["id"], "name": d["name"]}
    for d in districts if d.get("pid") in provinces
]

# 保存为 CSV
with open("city_ids.csv", "w", newline="", encoding="utf-8-sig") as f:
    csv.DictWriter(f, fieldnames=["id", "name"]).writeheader()
    csv.DictWriter(f, fieldnames=["id", "name"]).writerows(cities)

print(f"成功提取并保存 {len(cities)} 个城市数据")

数据会以csv表格的形式,保存在运行脚本的目录下,数据标签包括:市级行政区id、市级行政区名称;

我们通过查询不同区域,发现只有行政区id发生了变化,那么我们挨个替换成其他的行政区id即可遍历全国的门店,另外这里pageSize:表示每页显示的数据量或每次请求返回的最大记录数,也就是每次请求最多返回1000条数据,但是一般城市门店体量达不到这个水平,所以这里就不用考虑页数这个参数了;

第二步:利用GET请求获取所有门店列表,并根据标签进行保存,另存为csv;

完整代码#运行环境 Python 3.11

import requests
import csv
import time
import os
from urllib.parse import urlencode

# ==================== 配置区 ====================
CITY_INPUT_FILE = "city_ids.csv"           # 输入:城市ID列表(由前一个脚本生成)
OUTPUT_FILE = "oneplus_stores.csv"     # 输出:所有门店汇总数据

# 请求配置
API_URL = "https://opsiteapi-cn.oneplus.com/api/public/v1/store/getStoresByDistrictId"
DELAY = 0.6  # 每次请求间隔(秒),建议不低于 0.5
TIMEOUT = 10  # 请求超时时间(秒)

# 请求头(模拟浏览器访问)
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",
    "Accept": "application/json",
    "Referer": "https://www.oneplus.com/cn/store"
}

# CSV 表头字段
FIELDNAMES = [
    "store_id",
    "store_name",
    "city_name",         # 城市名称(来自 city_ids.csv)
    "district_name",     # 实际行政区域名(如“铜梁区”)
    "address",           # 地址描述
    "longitude",
    "latitude",
    "phone",
    "opening_hours",     # 营业时间
    "status",            # 状态:on=营业中
    "brand",
    "source_district_id" # 请求时使用的城市ID
]


def load_city_ids(csv_file):
    """从 CSV 文件加载城市ID列表(自动处理 BOM)"""
    if not os.path.exists(csv_file):
        print(f"错误:找不到文件 '{csv_file}',请先运行城市ID提取脚本!")
        return None

    cities = []
    # 关键:使用 'utf-8-sig' 自动去除 BOM
    with open(csv_file, mode='r', encoding='utf-8-sig') as f:
        reader = csv.DictReader(f)
        for row in reader:
            try:
                # 调试:打印第一行字段名
                if not cities:
                    print(f"检测到字段名: {list(row.keys())}")
                city_id = int(row["id"])
                city_name = row["name"]
                cities.append({"id": city_id, "name": city_name})
            except Exception as e:
                print(f"忽略无效行: {row} -> {e}")
    print(f"成功加载 {len(cities)} 个城市ID")
    return cities


def fetch_stores(district_id, city_name):
    """根据 districtId 获取门店列表"""
    params = {
        "districtId": district_id,
        "pageIndex": 1,
        "pageSize": 1000
    }
    url = API_URL + "?" + urlencode(params)

    try:
        response = requests.get(url, headers=HEADERS, timeout=TIMEOUT)
        if response.status_code != 200:
            print(f"[{city_name}] 请求失败,HTTP {response.status_code}")
            return None

        data = response.json()
        if data.get("code") != "0" or data.get("msg") != "ok":
            print(f"[{city_name}] 接口返回错误: {data.get('msg')}")
            return None

        # 关键:数据在 data.rows 中
        stores = data.get("data", {}).get("rows", [])
        print(f"[{city_name}] 获取到 {len(stores)} 家门店")
        return stores

    except requests.exceptions.Timeout:
        print(f"[{city_name}] 请求超时")
    except requests.exceptions.RequestException as e:
        print(f"[{city_name}] 网络错误: {e}")
    except Exception as e:
        print(f"[{city_name}] 解析JSON失败: {e}")
    return None


def extract_store_data(store, city_name, source_id):
    """提取门店所需字段"""
    return {
        "store_id": store.get("id"),
        "store_name": store.get("name"),
        "city_name": city_name,
        "district_name": store.get("districtName"),
        "address": store.get("description"),  # 实际地址在 description 字段
        "longitude": store.get("longitude"),
        "latitude": store.get("latitude"),
        "phone": store.get("shopTelephone"),
        "opening_hours": store.get("openingHour"),
        "status": store.get("status"),
        "brand": store.get("brand"),
        "source_district_id": source_id
    }


def main():
    print("开始批量获取 OnePlus 门店信息...\n")

    # 1. 加载城市ID(自动处理 BOM)
    cities = load_city_ids(CITY_INPUT_FILE)
    if not cities:
        return

    # 2. 准备输出文件
    output_count = 0
    with open(OUTPUT_FILE, mode='w', encoding='utf-8', newline='') as f:
        writer = csv.DictWriter(f, fieldnames=FIELDNAMES)
        writer.writeheader()

        # 3. 遍历每个城市
        for idx, city in enumerate(cities, start=1):
            city_name = city["name"]
            city_id = city["id"]

            print(f"[{idx:3d}/{len(cities)}] 正在获取: {city_name} (ID: {city_id})")
            stores = fetch_stores(city_id, city_name)

            if stores:
                for s in stores:
                    data = extract_store_data(s, city_name, city_id)
                    writer.writerow(data)
                output_count += len(stores)

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

    # 4. 完成
    print(f"\n所有请求完成!")
    print(f"共获取 {output_count} 家门店信息")
    print(f"已保存至: '{OUTPUT_FILE}'")


if __name__ == "__main__":
    main()

获取数据标签如下:store_id(店铺ID)、store_name(店铺名称)、city_name(所在城市)、district_name(所在区县)、address(店铺地址)、lng & lat(地理坐标)、phone(电话)、opening_hours(营业时间)、status(营业状态),其他一些非关键标签,这里省略;

因为在2021年一加已经成为OPPO旗下的子品牌,并且一加手机已全面进驻OPPO线下渠道,所以这里一加手机的门店与OPPO高度重合;

第三步:坐标系转换,由于vivo 体验店门店数据使用的是高德坐标系(GCJ02),为了在ArcGIS上准确展示而不发生偏移,我们需要将门店的坐标从GCJ02转换为WGS-84坐标系。我们可以利用coord-convert库中的gcj2wgs(lng, lat)函数,也可以用免费这个网站:批量转换工具:地图坐标系批量转换 - 免费在线工具
对CSV文件中的服务网点坐标列进行转换,完成坐标转换后,再将数据导入ArcGIS进行可视化;

接下来,我们进行看图说话:

一加授权零售店与OPPO的高度重合体现了两者紧密的兄弟品牌关系,尤其是在2021年一加成为OPPO旗下子品牌后,双方在线下渠道上的整合更加明显。从门店分布特征来看,这种整合策略带来了显著的市场覆盖效果。首先,在经济发达、人口密集的华东和华南地区,门店密度最高,几乎覆盖了所有主要城市及部分县级市,这表明一加/OPPO在这些区域的布局最为密集,以满足高需求市场。同时,北京、上海、广州、深圳等一线城市实现了全覆盖,不仅数量多,而且分布广泛,确保了核心商圈和商业中心的全面触及。

然而,当观察到西北、东北等地区的门店分布时,可以看出其门店数量相对较少,且多集中在省会或较大城市。这反映了在经济发展水平和人口密度较低的区域,一加/OPPO采取了更为谨慎的扩展策略。西南地区的成都、昆明等大城市虽然有一定的门店数量,但整体而言,这些区域的门店分布较为稀疏,显示出未来有较大的增长空间。

此外,二线城市如杭州、南京、武汉、成都、重庆等地也是重点布局区域,形成了完善的销售和服务网络。随着渠道下沉战略的推进,一加/OPPO也在逐步渗透至三四线城市及以下市场,许多县级市和中小城市也开始出现其授权零售店的身影,旨在扩大品牌的影响力和市场份额。

选址方面,大多数门店位于核心商圈、大型购物中心、交通枢纽附近以及年轻消费群体集中的高校周边和科技园区,以最大化地吸引目标客户并提供便捷的服务体验。基于不同区域的市场需求和消费特点,一加/OPPO也在不断优化门店结构,提供更加精准的产品和服务。

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