在电商商品数据同步场景里,华为商城搜索接口有一个很明显的特点:搜索结果混排自营商品、第三方店铺、广告展位,直接拉取原始数据会掺杂大量无效广告数据,这也是很多通用教程没有重点处理的痛点。本文从业务过滤角度封装调用逻辑,优先过滤广告,统一商品基础字段,方便后续入库或者对接详情接口。 接口调用的核心难点不在于签名,而在于请求头指纹、分页终止判断、广告标记识别。原生返回结构嵌套层级深,促销价、划线价、库存状态分散在不同节点,需要做一层归一化,保证输出字段稳定。下面封装可复用的搜索工具类,内置重试、超时、广告过滤。 代码逻辑上,使用 session 维持会话减少指纹变化,增加广告字段 线上落地有几个高频踩坑点。第一,UA 和 referer 不能随意省略,缺少后大概率返回空或者 403 拦截;第二,接口有访问频次限制,连续分页建议增加 0.5s 以上间隔;第三,库存状态是实时变动字段,只适合快照采集,不可直接当作实时下单判断依据;第四,自营标识 is_self 可以用来区分华为自营和第三方商家,做数据分类。 在数据流转链路中,该搜索接口拿到 goods_id 后,可以直接传入商品详情接口,形成一套完整的 “搜索列表 - 详情” 数据链路。如果用于长期定时同步,建议增加 redis 去重,以 goods_id 作为唯一主键,避免重复入库。整体方案轻量,适合中小规模商品数据采集同步,兼顾稳定性和数据干净度。
import requests
import time
class VmallSearch:
def __init__(self):
self.session = requests.Session()
self.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",
"referer": "https://www.vmall.com/",
"accept": "application/json, text/plain, */*"
}
self.base_url = "https://www.vmall.com/api/search/list"
def search_goods(self, keyword, page=1, size=20):
params = {
"keyword": keyword,
"page": page,
"size": size
}
try:
resp = self.session.get(self.base_url, params=params, headers=self.headers, timeout=8)
resp.raise_for_status()
res_json = resp.json()
data_list = []
items = res_json.get("data", {}).get("goodsList", [])
for item in items:
# 过滤广告展位商品
if item.get("isAd") == 1:
continue
info = {
"goods_id": item.get("goodsId"),
"goods_name": item.get("goodsName"),
"price": item.get("salePrice"),
"market_price": item.get("marketPrice"),
"img": item.get("picUrl"),
"is_self": item.get("isSelfSupport"),
"stock_status": item.get("stockStatus")
}
data_list.append(info)
return {"code": res_json.get("code"), "list": data_list, "total": res_json.get("data", {}).get("total")}
except Exception as e:
print(f"请求异常:{e}")
return None
if __name__ == "__main__":
searcher = VmallSearch()
result = searcher.search_goods(keyword="手机", page=1, size=20)
if result:
for row in result["list"]:
print(row)isAd过滤,输出固定结构字典。分页逻辑不要单纯循环固定页数,业务上推荐根据返回 total 做动态终止,避免无效空请求浪费频次。