本篇文章將利用GET請求從OPPO官方網站或公開接口中獲取官方授權體驗店的分布信息,并通過Python編程語言中的requests庫來實現HTTP請求,從而提取詳細的門店位置數據。隨著OPPO品牌的發展和市場布局的擴展,其官方授權體驗店已經遍布全國各大城市和地區,成為連接消費者與品牌的橋梁。因此,掌握如何高效地從網絡資源中抓取這些信息變得尤為重要。
首先,我們將探討如何使用Python的requests庫發送GET請求以訪問OPPO官方網站或API接口。這包括設置正確的請求頭(headers),以便模擬真實的瀏覽器行為,避免被服務器識別為自動化腳本而拒絕服務。接下來,我們會詳細講解如何解析返回的數據——無論是JSON格式還是HTML頁面內容——從中提取所需的門店信息,如店鋪名稱、地址、經緯度坐標、營業時間等。
在成功獲取數據后,本文還將介紹如何對這些原始數據進行清洗和結構化處理,使其更加適合后續分析。例如,可以將數據轉換成易于管理和查詢的表格形式,或者導入到數據庫中。通過對這些結構化數據的深入分析,我們可以揭示OPPO在全國范圍內的市場滲透策略、不同城市的布局密度及其與當地人口消費特征之間的關系。
OPPO官方授權體驗店門店查詢:OPPO 官方授權體驗店查詢 | OPPO 官方網站
首先,我們找到門店數據的存儲位置,然后看3個關鍵部分標頭、負載、?預覽;
標頭:通常包括URL的連接,也就是目標資源的位置;
負載:對于GET請求:負載通常包含了傳遞的參數,有些網頁負載可能為空,或者沒有負載,因為所有參數都通過URL傳遞,這里我們可以看到城市編碼,當前頁數,還是明文,沒有進行加密;
預覽:指的是對響應內容的快速查看或摘要顯示,可以幫助用戶快速了解返回的數據結構或內容片段;
接下來就是數據獲取部分,先講一下方法思路,一共三個步驟;
方法思路
- 找到對應數據存儲位置,獲取所有店鋪列表的相關標簽數據;
- 我們通過獲取和改變行政區編碼,來遍歷全國門店數據;
- 地址轉經緯度,通過coord-convert庫實現GCJ-02轉WGS84;
第一步:我們先找到對應數據存儲位置,獲取所有門店列表,經過測試,這里可以選擇"通過行政區篩選",再選擇"所有區域",每個區域會根據頁數生成對應數量的html,我們通過修改行政區編碼來進行數據獲取,為了方便我們可以建立一個包含市級行政區????編碼的字典,通過遍歷行政區編碼來查詢全國數據;
通過測試發現非直轄市,數據要想選到"所有區域",就得選擇到市,以河北省為例,就是河北省→石家莊市,當然數據同樣是通過改變編碼進行傳遞的,但是這里是通過查詢一個省,返回一個響應,所以意味著要查詢所有省和自治區,才能知道所有編碼;
但是我國的行政區編碼通常都是一致的,所有我們去中華人民共和國民政部找最新的行政區劃編碼,下載下來;
通常,中國的行政區劃編碼規則如下:
- 省級:前兩位有效,后四位為 0000(如 110000 北京市)
- 市級:前四位有效,后兩位為 00,且不是 0000(如 110100 北京市市轄區)
- 縣級:六位均為有效數字(如 110101 東城區)
因此,我們可以通過判斷編碼是否滿足 XXXX00 且不等于 XXXX00(排除省級)來提取市級編碼;
完整代碼#運行環境 Python 3.11
# -*- coding: utf-8 -*-
import requests
from bs4 import BeautifulSoup
import csv# 配置表頭
url = "https://www.mca.gov.cn/mzsj/xzqh/2023/202301xzqh.html"
headers = {"User-Agent": "Mozilla/5.0"}
output_file = "city_codes_2023.csv"# 獲取并解析
print("正在獲取數據...")
res = requests.get(url, headers=headers)
res.encoding = 'utf-8'
soup = BeautifulSoup(res.text, 'html.parser')data = []
for row in soup.find_all('tr'):cells = row.find_all('td')if len(cells) >= 3:code = cells[1].get_text(strip=True)name = ''.join(cells[2].get_text().split()) # 清理空白if code.isdigit() and len(code) == 6 and code.endswith('00') and not code.endswith('0000'):if name not in ['市轄區', '縣']:data.append((code, name))# 保存為CSV(帶BOM,兼容Excel)
with open(output_file, 'w', encoding='utf-8-sig', newline='') as f:writer = csv.writer(f)writer.writerow(['編碼', '名稱'])writer.writerows(data)print(f"完成!共提取 {len(data)} 個市級單位,已保存為 '{output_file}'")
獲取數據標簽如下,城市編碼城市名稱,數據保存為city_codes_2023.csv,這里需要把上海(310100)、北京(110100)、天津(120100)、重慶(500100)這些直轄市手動加上,需要注意的是,例如北京市行政區劃代碼為110000,其中,110100為市轄區匯總碼,所以這里直轄市使用的都是市轄區匯總碼;
第二步:利用GET請求獲取所有門店列表,并根據標簽進行保存,另存為csv;
完整代碼#運行環境 Python 3.11
# -*- coding: utf-8 -*-import requests
import csv
import time
from datetime import datetime# ================== 配置 ==================
CSV_INPUT = "city_codes_2023.csv" # 城市編碼文件(含 "編碼" 列)
CSV_OUTPUT = "oppo_shops_all_cities.csv" # 輸出文件
API_URL = "https://opsiteapi-cn.oppo.com/api/public/v1/sfa/search"
HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36","Referer": "https://www.oppo.com/"
}
PAGE_SIZE = 100
DELAY = 0.5 # 每個城市請求后延遲0.5秒,禮貌爬取# ================== 讀取城市編碼 ==================
def load_city_codes(filename):codes = []try:with open(filename, 'r', encoding='utf-8-sig') as f:reader = csv.DictReader(f)for row in reader:code = row.get("編碼", "").strip()if code.isdigit() and len(code) == 6:codes.append(code)print(f"加載 {len(codes)} 個城市編碼")except FileNotFoundError:print(f"錯誤:未找到文件 {filename},請確保 city_codes_2023.csv 存在")return []except Exception as e:print(f"讀取城市編碼失敗: {e}")return []return codes# ================== 獲取單個城市的所有門店數據 ==================
def fetch_all_pages(gid):all_shops = []page_no = 1while True:params = {"gid": gid,"shopType": "3","operateStatusList": "2","pageNo": page_no,"pageSize": PAGE_SIZE}try:response = requests.get(API_URL, params=params, headers=HEADERS, timeout=10)response.raise_for_status()data = response.json()if data.get("code") != "0":print(f"API 返回異常 (gid={gid}, page={page_no}): {data.get('message', 'Unknown')}")breakrecords = data["data"]["records"]all_shops.extend(records)# 獲取總頁數total_pages = data["data"]["pages"]print(f"獲取 gid={gid} 第 {page_no}/{total_pages} 頁,共 {len(records)} 條")if page_no >= total_pages:breakpage_no += 1time.sleep(0.1) # 短暫延遲,避免頻率過高except Exception as e:print(f"請求 gid={gid} 第 {page_no} 頁失敗: {e}")breakreturn all_shops# ================== 保存所有門店數據 ==================
def save_to_csv(all_shops, filename):fieldnames = ["city_gid", "id", "name", "code", "fullShopAddress","lng", "lat", "shopBusinessStart", "shopBusinessEnd", "shopContactNumber"]with open(filename, "w", encoding="utf-8-sig", newline="", errors="replace") as f:writer = csv.DictWriter(f, fieldnames=fieldnames)writer.writeheader()for shop in all_shops:loc = shop.get("locationDTO", {}) or {}writer.writerow({"city_gid": shop.get("city_gid"), # 標記來源城市"id": shop["id"],"name": shop["name"],"code": shop["code"],"fullShopAddress": loc.get("fullShopAddress", ""),"lng": loc.get("lng", ""),"lat": loc.get("lat", ""),"shopBusinessStart": shop.get("shopBusinessStart", ""),"shopBusinessEnd": shop.get("shopBusinessEnd", ""),"shopContactNumber": shop.get("shopContactNumber", "")})print(f"所有數據已保存至: {filename}")# ================== 主函數 ==================
def main():print(f"開始獲取 OPPO 門店數據 | {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")# 1. 加載城市編碼city_codes = load_city_codes(CSV_INPUT)if not city_codes:returnall_shops = []success_count = 0fail_count = 0# 2. 遍歷每個城市for i, gid in enumerate(city_codes, 1):print(f"[{i}/{len(city_codes)}] 正在獲取城市 gid={gid} 的門店數據...")shops = fetch_all_pages(gid)# 添加城市標識for shop in shops:shop["city_gid"] = gidif shops:all_shops.extend(shops)success_count += 1else:fail_count += 1time.sleep(DELAY) # 控制請求頻率# 3. 保存結果if all_shops:save_to_csv(all_shops, CSV_OUTPUT)print(f"完成!共獲取 {len(all_shops)} 條門店數據,來自 {success_count} 個城市")if fail_count > 0:print(f"{fail_count} 個城市獲取失敗")else:print("未獲取到任何門店數據")# ================== 運行 ==================
if __name__ == "__main__":main()
獲取數據標簽如下,city_gid(行政區id)、id(門店id)、name(門店名稱)、fullShopAddress(門店地址)、lng & lat(地理坐標)、shopBusinessStart(開始營業時間)、shopBusinessEnd(結束營業時間)、shopContactNumber(門店電話),其他一些非關鍵標簽,這里省略;
第三步:坐標系轉換,由于OPPO官方授權體驗店門店數據使用的是高德坐標系(GCJ02),為了在ArcGIS上準確展示而不發生偏移,我們需要將門店的坐標從GCJ02轉換為WGS-84坐標系。我們可以利用coord-convert庫中的gcj2wgs(lng, lat)函數,也可以用免費這個網站:批量轉換工具:地圖坐標系批量轉換 - 免費在線工具;
對CSV文件中的服務網點坐標列進行轉換,完成坐標轉換后,再將數據導入ArcGIS進行可視化;
接下來,我們進行看圖說話:
OPPO官方授權體驗店在中國呈現出明顯的地域性差異。高度集中的現象主要出現在東部和南部地區,尤其是華東、華南以及華中地區,這些區域店鋪的數量顯著多于其他地區。這表明OPPO在這些經濟發達、人口密集且消費能力較強的區域有著更為廣泛的布局。相對而言,稀疏分布的情況則出現在西北、東北及青藏高原等地理環境較為復雜的地區。
具體來看,在東部沿海地區,包括山東、江蘇、浙江、福建和廣東等省份,是體驗店最為密集的地方。這里不僅是我國經濟發展的前沿陣地,也是電子消費品的主要市場之一。城市覆蓋廣的特點不僅體現在省會城市和大城市,還包括了一些中小城市,顯示出OPPO對于該地區市場的重視程度。而在中部地區,如河南、湖北、湖南等地,則構成了次級集中區。盡管店鋪數量不及東部沿海,但依然反映出這些地區擁有較大的市場潛力和發展空間。
相比之下,西部和北部地區的分布顯得較為稀疏。例如新疆、青海、西藏、內蒙古以及黑龍江等省份,由于地理環境、人口密度及經濟發展水平等因素的影響,這里的體驗店數量較少。不過,即便是這些地區,OPPO也傾向于選擇省會城市或較大的城市進行重點布局,如烏魯木齊、呼和浩特等,以確保品牌影響力和服務質量。
影響上述分布的因素眾多,其中經濟因素扮演著重要角色。經濟發展水平和商業氛圍較好的地方往往更受青睞;同時,人口因素也不可忽視,人口密度高且年輕人口比例大的地區,對于電子產品的需求量更大。此外,政策因素同樣起到了推動作用,比如部分地區可能享有政府提供的稅收優惠或者租金補貼等支持措施。
展望未來,OPPO有望繼續深化其在東部和中部市場的戰略布局,進一步增加體驗店數量,并提升服務質量。與此同時,隨著國家對西部大開發和東北振興等戰略的支持力度加大,逐步拓展西部和北部市場也將成為可能。通過不斷優化店面選址和運營策略,OPPO可以根據不同地區的市場需求提供更加個性化和優質的服務,滿足廣大消費者的需求。
文章僅用于分享個人學習成果與個人存檔之用,分享知識,如有侵權,請聯系作者進行刪除。所有信息均基于作者的個人理解和經驗,不代表任何官方立場或權威解讀。