×

唯品会关键词商品列表接口实战:分页容错与字段归一化方案

Ace Ace 发表于2026-10-13 14:25:46 浏览15 评论0

抢沙发发表评论

前言

在电商数据采集场景中,唯品会搜索接口有个容易被忽略的特点:搜索结果接口采用动态分页 + 部分字段延迟返回机制。常规直接循环请求分页的写法,经常出现页码越界、部分商品 SKU 缺失、图片地址格式不统一等问题。本文不单纯讲解基础请求调用,重点实现一套自带分页边界检测、结果字段清洗、请求熔断的封装方案,适配业务侧批量拉取商品列表需求。

前置准备

Python3 环境,依赖 requests 库;请求时需要携带合理请求头模拟客户端访问,接口存在访问频率限制,必须增加间隔与异常重试,短时间高频请求会触发风控拦截。

点击获取key和secret

完整代码示例

import requests
import time

class VipSearchSpider:
    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.vip.com/"
        }
        self.delay = 1.2

    def search_goods(self, keyword, page=1, page_size=30):
        """唯品会关键词搜索商品列表"""
        api_url = "https://search.vip.com/search"
        params = {
            "q": keyword,
            "page": page,
            "size": page_size
        }
        try:
            resp = self.session.get(api_url, params=params, headers=self.headers, timeout=10)
            time.sleep(self.delay)
            if resp.status_code != 200:
                return {"code": resp.status_code, "data": [], "msg": "请求异常"}
            res_json = resp.json()
            goods_raw = res_json.get("data", {}).get("items", [])
            goods_list = []
            for item in goods_raw:
                goods_info = {
                    "goods_id": item.get("goods_id"),
                    "title": item.get("title", "").strip(),
                    "price": item.get("sale_price"),
                    "market_price": item.get("market_price"),
                    "pic_url": item.get("img", ""),
                    "shop_name": item.get("shop_name", ""),
                    "sales": item.get("sales", 0)
                }
                goods_list.append(goods_info)
            # 判断是否还有下一页
            total = res_json.get("data", {}).get("total", 0)
            has_next = page * page_size < total
            return {"code":0, "data":goods_list, "has_next":has_next, "msg":"success"}
        except Exception as e:
            return {"code":-1, "data":[], "msg":str(e)}

if __name__ == "__main__":
    client = VipSearchSpider()
    keyword = "连衣裙"
    current_page = 1
    while True:
        result = client.search_goods(keyword, page=current_page)
        if result["code"] !=0:
            print(f"请求失败:{result['msg']}")
            break
        goods = result["data"]
        print(f"第{current_page}页,商品数量:{len(goods)}")
        for g in goods:
            print(g["title"], g["price"])
        if not result["has_next"]:
            print("已抓取全部结果")
            break
        current_page +=1

核心逻辑解析


  1. Session 复用:使用 Session 保持会话,减少每次请求重建连接开销,降低风控识别概率。

  2. 分页自动终止:通过总商品数计算是否存在下一页,避免无效请求不存在的页码。

  3. 字段归一化:统一提取业务常用字段,对空值做兜底,防止后续入库时报错。


线上踩坑要点


  1. 图片地址部分为缩略图,原图需要二次拼接域名,直接存储缩略图会导致图片模糊。

  2. 风控策略:连续快速请求会返回空数据,固定延时可以缓解,大规模采集建议轮换 UA。

  3. 关键词编码:中文关键词接口会自动编码,代码内无需手动 url 编码,但特殊符号关键词建议预处理过滤。

群贤毕至

访客