<?xml version="1.0" encoding="utf-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>万邦api博客</title><link>https://apiproxylog.com/</link><description>Good Luck To You!</description><item><title>苏宁商品详情接口开发实践：参数组结构化解析与异常码拦截方案</title><link>https://apiproxylog.com/?id=253</link><description>&lt;div class=&quot;Post-RichTextContainer&quot;&gt;&lt;div class=&quot;css-1od93p9&quot;&gt;&lt;div class=&quot;css-376mun&quot;&gt;&lt;span id=&quot;content&quot;&gt;&lt;div class=&quot;RichText ztext Post-RichText css-u8299y&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;pizJi1wO&quot;&gt;前言&lt;/p&gt;&lt;p data-pid=&quot;nTtUns3j&quot;&gt;苏宁开放平台商品详情接口和多数电商接口有明显区别：返回数据嵌套层级多，商品参数为多组循环数组，同时接口采用独立异常码体系。常规直接取 JSON 字段的写法，很容易出现规格参数入库困难、活动价与日常价混淆、接口异常漏判问题。本文不只是简单演示接口调用，重点封装一套参数结构化解析、异常码拦截、自动重试的工具类，适合商品数据同步、比价业务场景。&lt;/p&gt;&lt;p data-pid=&quot;DEHGwVj7&quot;&gt;前置准备&lt;/p&gt;&lt;p data-pid=&quot;EFbuLi3m&quot;&gt;Python3 环境，依赖 requests 库。调用苏宁云台 API 需要提前申请 AppKey、AppSecret，请求报文需要按平台规则生成签名。接口有调用频次限制，高频请求会触发权限拦截，批量拉取需要控制请求间隔。&lt;/p&gt;&lt;figure data-size=&quot;normal&quot;&gt;&lt;div class=&quot;RichText-ConditionalImagePortal&quot;&gt;&lt;img src=&quot;https://picx.zhimg.com/80/v2-3af450c8bd70b976f7ecba45da8c7f8b_720w.jpg&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1162&quot; data-rawheight=&quot;575&quot; data-original-token=&quot;v2-09341ab3f71cad016bdfa28ad4c0cf52&quot; class=&quot;origin_image zh-lightbox-thumb lazy&quot; width=&quot;1162&quot; data-original=&quot;https://picx.zhimg.com/v2-3af450c8bd70b976f7ecba45da8c7f8b_r.jpg&quot; data-actualsrc=&quot;https://picx.zhimg.com/v2-3af450c8bd70b976f7ecba45da8c7f8b_1440w.jpg&quot; height=&quot;575&quot; data-lazy-status=&quot;ok&quot;/&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p data-pid=&quot;n4CJiPOS&quot;&gt;&lt;a href=&quot;https://o0b.cn/iiiace&quot; target=&quot;_blank&quot;&gt;点击获取key和secret&lt;/a&gt;&lt;/p&gt;&lt;p data-pid=&quot;a4B-r-XS&quot;&gt;完整代码示例&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;python
import&amp;nbsp;requests
import&amp;nbsp;time
import&amp;nbsp;hashlib

class&amp;nbsp;SuningDetailClient:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;app_key,&amp;nbsp;app_secret):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.app_key&amp;nbsp;=&amp;nbsp;app_key
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.app_secret&amp;nbsp;=&amp;nbsp;app_secret
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.session&amp;nbsp;=&amp;nbsp;requests.Session()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.retry_times&amp;nbsp;=&amp;nbsp;2
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.delay&amp;nbsp;=&amp;nbsp;1.4

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;build_sign(self,&amp;nbsp;params):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;苏宁接口签名生成&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sort_str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;.join([k+params[k]&amp;nbsp;for&amp;nbsp;k&amp;nbsp;in&amp;nbsp;sorted(params.keys())])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sign_raw&amp;nbsp;=&amp;nbsp;sort_str&amp;nbsp;+&amp;nbsp;self.app_secret
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;hashlib.md5(sign_raw.encode(&amp;quot;utf-8&amp;quot;)).hexdigest().upper()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_item_detail(self,&amp;nbsp;sku_id,&amp;nbsp;supplier_code):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;根据SKU编码获取苏宁商品详情，结构化解析参数&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;api_url&amp;nbsp;=&amp;nbsp;&amp;quot;https://open.suning.com/api/http/sopRequest&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;req_params&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;appKey&amp;quot;:&amp;nbsp;self.app_key,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;skuId&amp;quot;:&amp;nbsp;sku_id,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;supplierCode&amp;quot;:&amp;nbsp;supplier_code
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;req_params[&amp;quot;sign&amp;quot;]&amp;nbsp;=&amp;nbsp;self.build_sign(req_params)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;i&amp;nbsp;in&amp;nbsp;range(self.retry_times):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resp&amp;nbsp;=&amp;nbsp;self.session.post(api_url,&amp;nbsp;json=req_params,&amp;nbsp;timeout=12)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;time.sleep(self.delay)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;resp.status_code&amp;nbsp;!=&amp;nbsp;200:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;code&amp;quot;:&amp;nbsp;resp.status_code,&amp;nbsp;&amp;quot;data&amp;quot;:&amp;nbsp;None,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;&amp;quot;http请求失败&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;res_json&amp;nbsp;=&amp;nbsp;resp.json()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sn_body&amp;nbsp;=&amp;nbsp;res_json.get(&amp;quot;sn_body&amp;quot;,&amp;nbsp;{})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;res_json.get(&amp;quot;sn_error&amp;quot;):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;err_info&amp;nbsp;=&amp;nbsp;res_json[&amp;quot;sn_error&amp;quot;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;code&amp;quot;:-1,&amp;nbsp;&amp;quot;data&amp;quot;:None,&amp;nbsp;&amp;quot;msg&amp;quot;:f&amp;quot;{err_info[&amp;#39;error_code&amp;#39;]}:{err_info[&amp;#39;error_msg&amp;#39;]}&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw_detail&amp;nbsp;=&amp;nbsp;sn_body.get(&amp;quot;queryItemdetail&amp;quot;,&amp;nbsp;{})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;商品参数数组转为键值对，方便入库
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;param_map&amp;nbsp;=&amp;nbsp;{}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;p&amp;nbsp;in&amp;nbsp;raw_detail.get(&amp;quot;itemParameters&amp;quot;,&amp;nbsp;[]):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;param_map[p.get(&amp;quot;parName&amp;quot;)]&amp;nbsp;=&amp;nbsp;p.get(&amp;quot;parValue&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;detail_result&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sku_id&amp;quot;:&amp;nbsp;raw_detail.get(&amp;quot;skuId&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;raw_detail.get(&amp;quot;itemName&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;).strip(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;brand&amp;quot;:&amp;nbsp;raw_detail.get(&amp;quot;brandName&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sale_price&amp;quot;:&amp;nbsp;raw_detail.get(&amp;quot;price&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;stock&amp;quot;:&amp;nbsp;raw_detail.get(&amp;quot;invQty&amp;quot;,0),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;images&amp;quot;:&amp;nbsp;[raw_detail.get(f&amp;quot;supplierImg{i}Url&amp;quot;)&amp;nbsp;for&amp;nbsp;i&amp;nbsp;in&amp;nbsp;range(1,6)&amp;nbsp;if&amp;nbsp;raw_detail.get(f&amp;quot;supplierImg{i}Url&amp;quot;)],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;params&amp;quot;:&amp;nbsp;param_map,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;is_on_sale&amp;quot;:&amp;nbsp;raw_detail.get(&amp;quot;status&amp;quot;)&amp;nbsp;==&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;code&amp;quot;:0,&amp;nbsp;&amp;quot;data&amp;quot;:detail_result,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;quot;success&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception&amp;nbsp;as&amp;nbsp;e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;self.retry_times&amp;nbsp;-1:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;time.sleep(2)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;continue
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;code&amp;quot;:-1,&amp;nbsp;&amp;quot;data&amp;quot;:None,&amp;nbsp;&amp;quot;msg&amp;quot;:str(e)}

if&amp;nbsp;__name__&amp;nbsp;==&amp;nbsp;&amp;quot;__main__&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;client&amp;nbsp;=&amp;nbsp;SuningDetailClient(app_key=&amp;quot;your_key&amp;quot;,&amp;nbsp;app_secret=&amp;quot;your_secret&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ret&amp;nbsp;=&amp;nbsp;client.get_item_detail(sku_id=&amp;quot;123456789&amp;quot;,&amp;nbsp;supplier_code=&amp;quot;000000000&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;ret[&amp;quot;code&amp;quot;]&amp;nbsp;==0:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;item&amp;nbsp;=&amp;nbsp;ret[&amp;quot;data&amp;quot;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;商品名称：&amp;quot;,&amp;nbsp;item[&amp;quot;title&amp;quot;])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;商品参数：&amp;quot;,&amp;nbsp;item[&amp;quot;params&amp;quot;])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;查询失败：&amp;quot;,&amp;nbsp;ret[&amp;quot;msg&amp;quot;])&lt;/pre&gt;&lt;/div&gt;&lt;p data-pid=&quot;DNrsmTQ7&quot;&gt;核心逻辑解析&lt;/p&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;签名封装：实现平台 MD5 签名算法，自动排序参数生成签名，适配苏宁接口鉴权规则。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;参数结构化转换：将循环的商品参数数组转为键值字典，避免嵌套数组入库麻烦，便于检索。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;独立异常拦截：单独捕获 sn_error 节点，识别业务异常码，区分网络错误和业务权限错误。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;失败重试：网络抖动时自动重试，减少单次调用失败造成的数据缺失。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;p data-pid=&quot;YJmddxje&quot;&gt;线上踩坑要点&lt;/p&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;入参双必填：查询详情时 skuId 和 supplierCode 两个参数必须同时传入，缺少供应商编码直接返回无结果。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;图片字段分散：商品图分 5 个独立字段，代码统一收集过滤空链接，避免无效图片地址入库。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;状态校验：下架商品依然返回基础标题，需要 status 字段校验在售状态。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;限流控制：单账号 QPS 有限制，批量同步需要做队列限速，短时间高频调用会返回权限异常码。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;span id=&quot;VirtualCatalogAnchorPoint&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div class=&quot;Reward&quot;&gt;&lt;button class=&quot;Reward-activateBtn&quot;&gt;开启送礼物&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Thu, 15 Oct 2026 13:44:56 +0800</pubDate></item><item><title>唯品会商品详情接口开发实践：SKU 扁平化与促销字段过滤方案</title><link>https://apiproxylog.com/?id=252</link><description>&lt;p&gt;&lt;span id=&quot;content&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;wd-6S9PY&quot;&gt;前言&lt;/p&gt;&lt;p data-pid=&quot;cxnIwYzw&quot;&gt;在商品数据同步业务中，唯品会详情接口最大难点不是基础请求，而是嵌套多层的 SKU 规格、动态促销标签与限时价格。常规直接读取原始返回 JSON 的写法，经常出现规格数组入库困难、活动价和原价混淆、下架商品残留脏数据等问题。本文不只是简单演示接口调用，重点封装一套 SKU 扁平化、促销字段分离、异常重试的工具类，适用于商品数据同步、比价业务。&lt;/p&gt;&lt;p data-pid=&quot;wQVELZ7q&quot;&gt;前置准备&lt;/p&gt;&lt;p data-pid=&quot;9pnAuE3w&quot;&gt;Python3 环境，依赖 requests 库。接口存在会话校验，需要维持请求会话；平台会校验请求头，缺少 Referer 或者 UA 会直接返回数据为空。批量查询时必须增加请求间隔，高频调用会触发 IP 限流。&lt;/p&gt;&lt;figure data-size=&quot;normal&quot;&gt;&lt;div class=&quot;RichText-ConditionalImagePortal&quot;&gt;&lt;img src=&quot;https://pica.zhimg.com/80/v2-49c2c6a1938c08f91b885b3f8b4d3fd8_720w.webp&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1172&quot; data-rawheight=&quot;573&quot; data-original-token=&quot;v2-f6cca3e35f94163407e047c44a7bf550&quot; class=&quot;origin_image zh-lightbox-thumb lazy&quot; width=&quot;1172&quot; data-original=&quot;https://pica.zhimg.com/v2-49c2c6a1938c08f91b885b3f8b4d3fd8_r.jpg&quot; data-actualsrc=&quot;https://pica.zhimg.com/v2-49c2c6a1938c08f91b885b3f8b4d3fd8_1440w.jpg&quot; height=&quot;573&quot; data-lazy-status=&quot;ok&quot;/&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p data-pid=&quot;DgCc99h0&quot;&gt;&lt;a href=&quot;https://o0b.cn/iiiace&quot; target=&quot;_blank&quot;&gt;点击获取key和secret&lt;/a&gt;&lt;/p&gt;&lt;p data-pid=&quot;AXAW9rdx&quot;&gt;完整代码示例&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;python

import&amp;nbsp;requests
import&amp;nbsp;time

class&amp;nbsp;VipDetailClient:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.session&amp;nbsp;=&amp;nbsp;requests.Session()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.headers&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;User-Agent&amp;quot;:&amp;nbsp;&amp;quot;Mozilla/5.0&amp;nbsp;(Windows&amp;nbsp;NT&amp;nbsp;10.0;&amp;nbsp;Win64;&amp;nbsp;x64)&amp;nbsp;AppleWebKit/537.36&amp;nbsp;(KHTML,&amp;nbsp;like&amp;nbsp;Gecko)&amp;nbsp;Chrome/122.0.0.0&amp;nbsp;Safari/537.36&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;Referer&amp;quot;:&amp;nbsp;&amp;quot;https://www.vip.com/&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.retry_times&amp;nbsp;=&amp;nbsp;2
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.delay&amp;nbsp;=&amp;nbsp;1.3

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_goods_detail(self,&amp;nbsp;goods_id):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;根据商品ID获取详情，扁平化SKU数据&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;api_url&amp;nbsp;=&amp;nbsp;&amp;quot;https://api.vip.com/item/detail&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;params&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;itemId&amp;quot;:&amp;nbsp;goods_id
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;i&amp;nbsp;in&amp;nbsp;range(self.retry_times):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resp&amp;nbsp;=&amp;nbsp;self.session.get(api_url,&amp;nbsp;params=params,&amp;nbsp;headers=self.headers,&amp;nbsp;timeout=12)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;time.sleep(self.delay)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;resp.status_code&amp;nbsp;!=&amp;nbsp;200:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;code&amp;quot;:&amp;nbsp;resp.status_code,&amp;nbsp;&amp;quot;data&amp;quot;:&amp;nbsp;None,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;&amp;quot;http请求失败&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;res_json&amp;nbsp;=&amp;nbsp;resp.json()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw_data&amp;nbsp;=&amp;nbsp;res_json.get(&amp;quot;data&amp;quot;,&amp;nbsp;{})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku_list&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;扁平化SKU规格
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;sku&amp;nbsp;in&amp;nbsp;raw_data.get(&amp;quot;skuList&amp;quot;,&amp;nbsp;[]):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku_info&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sku_id&amp;quot;:&amp;nbsp;sku.get(&amp;quot;skuId&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;spec_name&amp;quot;:&amp;nbsp;sku.get(&amp;quot;spec&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sale_price&amp;quot;:&amp;nbsp;sku.get(&amp;quot;salePrice&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;market_price&amp;quot;:&amp;nbsp;sku.get(&amp;quot;marketPrice&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;stock_num&amp;quot;:&amp;nbsp;sku.get(&amp;quot;stock&amp;quot;,&amp;nbsp;0)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku_list.append(sku_info)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;detail_result&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;goods_id&amp;quot;:&amp;nbsp;raw_data.get(&amp;quot;itemId&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;raw_data.get(&amp;quot;title&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;).strip(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;brand_name&amp;quot;:&amp;nbsp;raw_data.get(&amp;quot;brandName&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;main_images&amp;quot;:&amp;nbsp;raw_data.get(&amp;quot;picList&amp;quot;,&amp;nbsp;[]),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;desc_html&amp;quot;:&amp;nbsp;raw_data.get(&amp;quot;description&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;promotion_tags&amp;quot;:&amp;nbsp;raw_data.get(&amp;quot;promotionTagList&amp;quot;,&amp;nbsp;[]),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sku_list&amp;quot;:&amp;nbsp;sku_list,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;is_on_sale&amp;quot;:&amp;nbsp;raw_data.get(&amp;quot;status&amp;quot;)&amp;nbsp;==&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;code&amp;quot;:0,&amp;nbsp;&amp;quot;data&amp;quot;:detail_result,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;quot;success&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception&amp;nbsp;as&amp;nbsp;e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;self.retry_times&amp;nbsp;-1:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;time.sleep(2)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;continue
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;code&amp;quot;:-1,&amp;nbsp;&amp;quot;data&amp;quot;:None,&amp;nbsp;&amp;quot;msg&amp;quot;:str(e)}

if&amp;nbsp;__name__&amp;nbsp;==&amp;nbsp;&amp;quot;__main__&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;client&amp;nbsp;=&amp;nbsp;VipDetailClient()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;item_id&amp;nbsp;=&amp;nbsp;&amp;quot;123456789&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ret&amp;nbsp;=&amp;nbsp;client.get_goods_detail(item_id)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;ret[&amp;quot;code&amp;quot;]&amp;nbsp;==0:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;item&amp;nbsp;=&amp;nbsp;ret[&amp;quot;data&amp;quot;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;商品标题：&amp;quot;,&amp;nbsp;item[&amp;quot;title&amp;quot;])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;SKU数量：&amp;quot;,&amp;nbsp;len(item[&amp;quot;sku_list&amp;quot;]))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;获取详情失败：&amp;quot;,&amp;nbsp;ret[&amp;quot;msg&amp;quot;])&lt;/pre&gt;&lt;/div&gt;&lt;p data-pid=&quot;yRhEafe5&quot;&gt;核心逻辑解析&lt;/p&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;会话复用：使用 Session 保持 Cookie，减少每次请求握手开销，降低风控识别概率。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;SKU 扁平化处理：将多层嵌套的 SKU 规格提取为一维数组，方便直接写入数据库，避免嵌套 JSON 入库解析麻烦。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;促销标签独立存放：把活动标签单独拆分，和基础价格隔离，防止业务误把临时促销价作为日常售价。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;重试机制：网络抖动时自动重试，减少单次请求失败造成的数据丢失。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;p data-pid=&quot;NqDKg-aX&quot;&gt;线上踩坑要点&lt;/p&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;商品状态校验：下架商品接口依然会返回基础标题，必须通过 status 字段判断在售状态，避免同步无效商品。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;图片地址：详情描述内图片为相对路径，业务使用时需要拼接域名，否则图片无法正常加载。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;价格类型：价格字段为字符串类型，入库前建议转为浮点，空价格需要做兜底处理，防止程序抛出类型异常。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;限流策略：单次查询间隔建议大于 1 秒，大规模同步建议使用代理 IP 轮换。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Wed, 14 Oct 2026 16:23:00 +0800</pubDate></item><item><title>唯品会关键词商品列表接口实战：分页容错与字段归一化方案</title><link>https://apiproxylog.com/?id=251</link><description>&lt;p&gt;&lt;span id=&quot;content&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;1KOjchPo&quot;&gt;前言&lt;/p&gt;&lt;p data-pid=&quot;LFF8qFO7&quot;&gt;在电商数据采集场景中，唯品会搜索接口有个容易被忽略的特点：搜索结果接口采用动态分页 + 部分字段延迟返回机制。常规直接循环请求分页的写法，经常出现页码越界、部分商品 SKU 缺失、图片地址格式不统一等问题。本文不单纯讲解基础请求调用，重点实现一套自带分页边界检测、结果字段清洗、请求熔断的封装方案，适配业务侧批量拉取商品列表需求。&lt;/p&gt;&lt;p data-pid=&quot;xdbSBvsO&quot;&gt;前置准备&lt;/p&gt;&lt;p data-pid=&quot;Np3dejZJ&quot;&gt;Python3 环境，依赖 requests 库；请求时需要携带合理请求头模拟客户端访问，接口存在访问频率限制，必须增加间隔与异常重试，短时间高频请求会触发风控拦截。&lt;/p&gt;&lt;figure data-size=&quot;normal&quot;&gt;&lt;div class=&quot;RichText-ConditionalImagePortal&quot;&gt;&lt;img src=&quot;https://picx.zhimg.com/80/v2-ae1fad20e609e5445938ac06eee773b1_720w.jpg&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1169&quot; data-rawheight=&quot;709&quot; data-original-token=&quot;v2-58bd363f36dc403f9c48701718100cd2&quot; class=&quot;origin_image zh-lightbox-thumb lazy&quot; width=&quot;1169&quot; data-original=&quot;https://picx.zhimg.com/v2-ae1fad20e609e5445938ac06eee773b1_r.jpg&quot; data-actualsrc=&quot;https://picx.zhimg.com/v2-ae1fad20e609e5445938ac06eee773b1_1440w.jpg&quot; height=&quot;709&quot; data-lazy-status=&quot;ok&quot;/&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p data-pid=&quot;1D7a0HwQ&quot;&gt;&lt;a href=&quot;https://o0b.cn/iiiace&quot; target=&quot;_blank&quot;&gt;点击获取key和secret&lt;/a&gt;&lt;/p&gt;&lt;p data-pid=&quot;-L36cy2z&quot;&gt;完整代码示例&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;import&amp;nbsp;requests
import&amp;nbsp;time

class&amp;nbsp;VipSearchSpider:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.session&amp;nbsp;=&amp;nbsp;requests.Session()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.headers&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;User-Agent&amp;quot;:&amp;nbsp;&amp;quot;Mozilla/5.0&amp;nbsp;(Windows&amp;nbsp;NT&amp;nbsp;10.0;&amp;nbsp;Win64;&amp;nbsp;x64)&amp;nbsp;AppleWebKit/537.36&amp;nbsp;(KHTML,&amp;nbsp;like&amp;nbsp;Gecko)&amp;nbsp;Chrome/120.0.0.0&amp;nbsp;Safari/537.36&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;Referer&amp;quot;:&amp;nbsp;&amp;quot;https://www.vip.com/&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.delay&amp;nbsp;=&amp;nbsp;1.2

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;search_goods(self,&amp;nbsp;keyword,&amp;nbsp;page=1,&amp;nbsp;page_size=30):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;唯品会关键词搜索商品列表&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;api_url&amp;nbsp;=&amp;nbsp;&amp;quot;https://search.vip.com/search&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;params&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;q&amp;quot;:&amp;nbsp;keyword,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;page&amp;quot;:&amp;nbsp;page,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;size&amp;quot;:&amp;nbsp;page_size
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resp&amp;nbsp;=&amp;nbsp;self.session.get(api_url,&amp;nbsp;params=params,&amp;nbsp;headers=self.headers,&amp;nbsp;timeout=10)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;time.sleep(self.delay)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;resp.status_code&amp;nbsp;!=&amp;nbsp;200:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;code&amp;quot;:&amp;nbsp;resp.status_code,&amp;nbsp;&amp;quot;data&amp;quot;:&amp;nbsp;[],&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;&amp;quot;请求异常&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;res_json&amp;nbsp;=&amp;nbsp;resp.json()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;goods_raw&amp;nbsp;=&amp;nbsp;res_json.get(&amp;quot;data&amp;quot;,&amp;nbsp;{}).get(&amp;quot;items&amp;quot;,&amp;nbsp;[])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;goods_list&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;item&amp;nbsp;in&amp;nbsp;goods_raw:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;goods_info&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;goods_id&amp;quot;:&amp;nbsp;item.get(&amp;quot;goods_id&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;item.get(&amp;quot;title&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;).strip(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;item.get(&amp;quot;sale_price&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;market_price&amp;quot;:&amp;nbsp;item.get(&amp;quot;market_price&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;pic_url&amp;quot;:&amp;nbsp;item.get(&amp;quot;img&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;shop_name&amp;quot;:&amp;nbsp;item.get(&amp;quot;shop_name&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sales&amp;quot;:&amp;nbsp;item.get(&amp;quot;sales&amp;quot;,&amp;nbsp;0)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;goods_list.append(goods_info)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;判断是否还有下一页
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;total&amp;nbsp;=&amp;nbsp;res_json.get(&amp;quot;data&amp;quot;,&amp;nbsp;{}).get(&amp;quot;total&amp;quot;,&amp;nbsp;0)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;has_next&amp;nbsp;=&amp;nbsp;page&amp;nbsp;*&amp;nbsp;page_size&amp;nbsp;&amp;lt;&amp;nbsp;total
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;code&amp;quot;:0,&amp;nbsp;&amp;quot;data&amp;quot;:goods_list,&amp;nbsp;&amp;quot;has_next&amp;quot;:has_next,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;quot;success&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception&amp;nbsp;as&amp;nbsp;e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;code&amp;quot;:-1,&amp;nbsp;&amp;quot;data&amp;quot;:[],&amp;nbsp;&amp;quot;msg&amp;quot;:str(e)}

if&amp;nbsp;__name__&amp;nbsp;==&amp;nbsp;&amp;quot;__main__&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;client&amp;nbsp;=&amp;nbsp;VipSearchSpider()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;keyword&amp;nbsp;=&amp;nbsp;&amp;quot;连衣裙&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;current_page&amp;nbsp;=&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while&amp;nbsp;True:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;client.search_goods(keyword,&amp;nbsp;page=current_page)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;result[&amp;quot;code&amp;quot;]&amp;nbsp;!=0:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;请求失败：{result[&amp;#39;msg&amp;#39;]}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;goods&amp;nbsp;=&amp;nbsp;result[&amp;quot;data&amp;quot;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;第{current_page}页，商品数量：{len(goods)}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;g&amp;nbsp;in&amp;nbsp;goods:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(g[&amp;quot;title&amp;quot;],&amp;nbsp;g[&amp;quot;price&amp;quot;])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;result[&amp;quot;has_next&amp;quot;]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;已抓取全部结果&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;current_page&amp;nbsp;+=1&lt;/pre&gt;&lt;/div&gt;&lt;p data-pid=&quot;WAe_glBB&quot;&gt;核心逻辑解析&lt;/p&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;Session 复用：使用 Session 保持会话，减少每次请求重建连接开销，降低风控识别概率。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;分页自动终止：通过总商品数计算是否存在下一页，避免无效请求不存在的页码。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;字段归一化：统一提取业务常用字段，对空值做兜底，防止后续入库时报错。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;p data-pid=&quot;u99hsp_1&quot;&gt;线上踩坑要点&lt;/p&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;图片地址部分为缩略图，原图需要二次拼接域名，直接存储缩略图会导致图片模糊。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;风控策略：连续快速请求会返回空数据，固定延时可以缓解，大规模采集建议轮换 UA。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;关键词编码：中文关键词接口会自动编码，代码内无需手动 url 编码，但特殊符号关键词建议预处理过滤。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Tue, 13 Oct 2026 14:25:46 +0800</pubDate></item><item><title>VVIC 平台根据商品链接解析商品详情接口实践</title><link>https://apiproxylog.com/?id=250</link><description>&lt;p&gt;&lt;span id=&quot;content&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;fggcMO0O&quot;&gt;前言&lt;/p&gt;&lt;p data-pid=&quot;SJ574OqS&quot;&gt;在服饰供应链采集场景中，很多方案习惯用商品 ID 请求 VVIC 详情接口，但业务侧经常只有前端商品链接，需要先从 URL 提取唯一标识再拉取数据。本文不再单纯演示基础请求调用，重点实现&lt;strong&gt;链接自动解析 + 异常 URL 容错 + 多规格数据扁平化&lt;/strong&gt;，解决链接格式多变、SKU 数组嵌套、图片地址加密等线上痛点，代码增加重试与字段过滤，适合批量爬虫、供应链数据同步场景。&lt;/p&gt;&lt;p data-pid=&quot;w1KEvnRB&quot;&gt;前置准备&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;依赖：requests 库，用于 HTTP 请求&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;权限说明：接口调用需携带合法请求头，模拟客户端访问，高频请求建议增加延时，避免触发风控&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;输入：VVIC 商品详情页 URL，自动提取商品编号，无需手动截取 ID&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;figure data-size=&quot;normal&quot;&gt;&lt;div class=&quot;RichText-ConditionalImagePortal&quot;&gt;&lt;img src=&quot;https://pic4.zhimg.com/80/v2-5f09c670e1f530aeebb150f994adad6f_720w.jpg&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1165&quot; data-rawheight=&quot;601&quot; data-original-token=&quot;v2-6170b72ca099d47fc1c171fb7f1b7250&quot; class=&quot;origin_image zh-lightbox-thumb lazy&quot; width=&quot;1165&quot; data-original=&quot;https://pic4.zhimg.com/v2-5f09c670e1f530aeebb150f994adad6f_r.jpg&quot; data-actualsrc=&quot;https://pic4.zhimg.com/v2-5f09c670e1f530aeebb150f994adad6f_1440w.jpg&quot; height=&quot;601&quot; data-lazy-status=&quot;ok&quot;/&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p data-pid=&quot;Wy2UUZD7&quot;&gt;&lt;a href=&quot;https://o0b.cn/iiiace&quot; target=&quot;_blank&quot;&gt;点击获取key和secret&lt;/a&gt;&lt;/p&gt;&lt;p data-pid=&quot;wkjT_lSd&quot;&gt;完整代码示例&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;import&amp;nbsp;re
import&amp;nbsp;requests
import&amp;nbsp;time

class&amp;nbsp;VvicDetailByUrl:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.session&amp;nbsp;=&amp;nbsp;requests.Session()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.headers&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;User-Agent&amp;quot;:&amp;nbsp;&amp;quot;Mozilla/5.0&amp;nbsp;(Windows&amp;nbsp;NT&amp;nbsp;10.0;&amp;nbsp;Win64;&amp;nbsp;x64)&amp;nbsp;AppleWebKit/537.36&amp;nbsp;(KHTML,&amp;nbsp;like&amp;nbsp;Gecko)&amp;nbsp;Chrome/120.0.0.0&amp;nbsp;Safari/537.36&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;Accept&amp;quot;:&amp;nbsp;&amp;quot;application/json,&amp;nbsp;text/plain,&amp;nbsp;*/*&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;Referer&amp;quot;:&amp;nbsp;&amp;quot;https://www.vvic.com/&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.retry_times&amp;nbsp;=&amp;nbsp;2

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;从商品url中提取商品id
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;parse_goods_id(self,&amp;nbsp;goods_url):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pattern&amp;nbsp;=&amp;nbsp;r&amp;#39;goods/(\d+)&amp;#39;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;res&amp;nbsp;=&amp;nbsp;re.search(pattern,&amp;nbsp;goods_url)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;res:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;res.group(1)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;None

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;获取商品详情
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_detail(self,&amp;nbsp;goods_url):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;goods_id&amp;nbsp;=&amp;nbsp;self.parse_goods_id(goods_url)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;goods_id:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;code&amp;quot;:&amp;nbsp;-1,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;&amp;quot;URL解析失败，无法提取商品ID&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;api_url&amp;nbsp;=&amp;nbsp;f&amp;quot;https://www.vvic.com/api/goods/detail?goodsId={goods_id}&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;i&amp;nbsp;in&amp;nbsp;range(self.retry_times):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resp&amp;nbsp;=&amp;nbsp;self.session.get(api_url,&amp;nbsp;headers=self.headers,&amp;nbsp;timeout=10)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;resp.status_code&amp;nbsp;==&amp;nbsp;200:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;data&amp;nbsp;=&amp;nbsp;resp.json()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self.format_data(data)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;time.sleep(0.8)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception&amp;nbsp;as&amp;nbsp;e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;请求异常，重试{i+1}：{str(e)}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;time.sleep(1)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;code&amp;quot;:&amp;nbsp;-2,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;&amp;quot;接口请求多次失败&amp;quot;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;数据扁平化清洗，提取业务核心字段
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;format_data(self,&amp;nbsp;raw):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;raw.get(&amp;quot;code&amp;quot;)&amp;nbsp;!=&amp;nbsp;0:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;raw
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;item&amp;nbsp;=&amp;nbsp;raw[&amp;quot;data&amp;quot;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku_list&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;sku&amp;nbsp;in&amp;nbsp;item.get(&amp;quot;skuList&amp;quot;,&amp;nbsp;[]):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku_list.append({
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;spec_name&amp;quot;:&amp;nbsp;sku.get(&amp;quot;specName&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;sku.get(&amp;quot;price&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;stock&amp;quot;:&amp;nbsp;sku.get(&amp;quot;stockNum&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;goods_name&amp;quot;:&amp;nbsp;item.get(&amp;quot;goodsName&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;goods_id&amp;quot;:&amp;nbsp;item.get(&amp;quot;goodsId&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;main_images&amp;quot;:&amp;nbsp;item.get(&amp;quot;mainImages&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;desc_images&amp;quot;:&amp;nbsp;item.get(&amp;quot;descImages&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;category_name&amp;quot;:&amp;nbsp;item.get(&amp;quot;categoryName&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;min_price&amp;quot;:&amp;nbsp;item.get(&amp;quot;minPrice&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;total_stock&amp;quot;:&amp;nbsp;item.get(&amp;quot;totalStock&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sku_info&amp;quot;:&amp;nbsp;sku_list
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;code&amp;quot;:&amp;nbsp;0,&amp;nbsp;&amp;quot;data&amp;quot;:&amp;nbsp;result}

if&amp;nbsp;__name__&amp;nbsp;==&amp;nbsp;&amp;#39;__main__&amp;#39;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;client&amp;nbsp;=&amp;nbsp;VvicDetailByUrl()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;url&amp;nbsp;=&amp;nbsp;&amp;quot;https://www.vvic.com/goods/123456&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ret&amp;nbsp;=&amp;nbsp;client.get_detail(url)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(ret)&lt;/pre&gt;&lt;/div&gt;&lt;p data-pid=&quot;69dsFHzh&quot;&gt;核心逻辑解读&lt;/p&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;URL 解析模块：正则表达式自动提取 goodsId，兼容带参数、末尾斜杠等多种不规则链接，省去人工截取。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;会话复用：使用 Session 保持 cookie，减少握手开销，批量采集场景性能更优。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;数据扁平化处理：原始返回 SKU 为嵌套数组，清洗后转为简易列表，方便直接入库。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Mon, 12 Oct 2026 15:17:01 +0800</pubDate></item><item><title>VVIC 平台关键词商品列表接口封装：批发商品分页拉取与数据降噪实践</title><link>https://apiproxylog.com/?id=249</link><description>&lt;p&gt;&lt;span id=&quot;content&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;NQsu9wL8&quot;&gt;前言&lt;/p&gt;&lt;p data-pid=&quot;AaOHJz_F&quot;&gt;VVIC 作为服饰货源批发平台，很多开发者对接关键词商品搜索接口时，容易踩分页参数错乱、多规格数据混杂、返回字段缺失等问题。市面上大多示例仅做简单请求演示，缺少业务层面的数据过滤、请求节流与异常兼容逻辑。本文从货源业务场景出发，实现可直接用于业务系统的接口封装，重点解决批发场景下的无效商品过滤、分页边界判断，代码增加重试与结果去重逻辑，适配批量货源采集需求。&lt;/p&gt;&lt;figure data-size=&quot;normal&quot;&gt;&lt;div class=&quot;RichText-ConditionalImagePortal&quot;&gt;&lt;img src=&quot;https://pic2.zhimg.com/80/v2-c2306c5ed2206693331756c705edbac9_720w.jpg&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1193&quot; data-rawheight=&quot;773&quot; data-original-token=&quot;v2-7fc903bbeeb15e72361989e6f8fda032&quot; class=&quot;origin_image zh-lightbox-thumb lazy&quot; width=&quot;1193&quot; data-original=&quot;https://pic2.zhimg.com/v2-c2306c5ed2206693331756c705edbac9_r.jpg&quot; data-actualsrc=&quot;https://pic2.zhimg.com/v2-c2306c5ed2206693331756c705edbac9_1440w.jpg&quot; height=&quot;773&quot; data-lazy-status=&quot;ok&quot;/&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p data-pid=&quot;YuxDIWl-&quot;&gt;前置准备&lt;/p&gt;&lt;p data-pid=&quot;sW6uEaL7&quot;&gt;对接前需要准备平台开放接口的 &lt;a href=&quot;https://o0b.cn/iiiace&quot; target=&quot;_self&quot;&gt;AccessKey 与 Secret&lt;/a&gt;，接口请求需要携带时间戳、签名串。依赖库仅使用 requests，无需重型框架，适合脚本或微服务调用。&lt;br/&gt; 安装依赖：&lt;/p&gt;&lt;p data-pid=&quot;9jNfWtfJ&quot;&gt;bash&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;pip install requests&lt;br/&gt;&lt;/p&gt;&lt;p data-pid=&quot;QFIEFB9z&quot;&gt;完整调用代码&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;import&amp;nbsp;requests
import&amp;nbsp;time
import&amp;nbsp;hashlib

class&amp;nbsp;VvicSearchApi:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;ak,&amp;nbsp;sk):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.ak&amp;nbsp;=&amp;nbsp;ak
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.sk&amp;nbsp;=&amp;nbsp;sk
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.base_url&amp;nbsp;=&amp;nbsp;&amp;quot;https://api.vvic.com/open/search/goods&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.session&amp;nbsp;=&amp;nbsp;requests.Session()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.session.headers.update({
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;User-Agent&amp;quot;:&amp;nbsp;&amp;quot;Mozilla/5.0&amp;nbsp;(compatible;&amp;nbsp;api-client/1.0)&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;Content-Type&amp;quot;:&amp;nbsp;&amp;quot;application/json&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;})

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_sign(self,&amp;nbsp;timestamp):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sign_str&amp;nbsp;=&amp;nbsp;f&amp;quot;{self.ak}{timestamp}{self.sk}&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;hashlib.md5(sign_str.encode()).hexdigest()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;search_goods(self,&amp;nbsp;keyword,&amp;nbsp;page=1,&amp;nbsp;page_size=20):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;timestamp&amp;nbsp;=&amp;nbsp;str(int(time.time()))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;params&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;accessKey&amp;quot;:&amp;nbsp;self.ak,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;timestamp&amp;quot;:&amp;nbsp;timestamp,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sign&amp;quot;:&amp;nbsp;self.get_sign(timestamp),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;keyword&amp;quot;:&amp;nbsp;keyword,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;page&amp;quot;:&amp;nbsp;page,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;pageSize&amp;quot;:&amp;nbsp;page_size
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resp&amp;nbsp;=&amp;nbsp;self.session.get(self.base_url,&amp;nbsp;params=params,&amp;nbsp;timeout=10)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;resp.json()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;业务状态校验
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;result.get(&amp;quot;code&amp;quot;)&amp;nbsp;!=&amp;nbsp;0:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;接口异常：{result.get(&amp;#39;msg&amp;#39;)}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;goods_list&amp;nbsp;=&amp;nbsp;result[&amp;quot;data&amp;quot;][&amp;quot;list&amp;quot;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;数据降噪：过滤下架、无库存商品
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;filter_list&amp;nbsp;=&amp;nbsp;[item&amp;nbsp;for&amp;nbsp;item&amp;nbsp;in&amp;nbsp;goods_list&amp;nbsp;if&amp;nbsp;item.get(&amp;quot;stockNum&amp;quot;,0)&amp;nbsp;&amp;gt;&amp;nbsp;0&amp;nbsp;and&amp;nbsp;item[&amp;quot;status&amp;quot;]&amp;nbsp;==&amp;nbsp;1]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;total&amp;quot;:&amp;nbsp;result[&amp;quot;data&amp;quot;][&amp;quot;total&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;page&amp;quot;:&amp;nbsp;page,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;goods&amp;quot;:&amp;nbsp;filter_list
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception&amp;nbsp;as&amp;nbsp;e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;请求失败：{str(e)}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;time.sleep(2)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;None

if&amp;nbsp;__name__&amp;nbsp;==&amp;nbsp;&amp;quot;__main__&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;api&amp;nbsp;=&amp;nbsp;VvicSearchApi(ak=&amp;quot;你的AccessKey&amp;quot;,&amp;nbsp;sk=&amp;quot;你的Secret&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;res&amp;nbsp;=&amp;nbsp;api.search_goods(keyword=&amp;quot;连衣裙&amp;quot;,&amp;nbsp;page=1,&amp;nbsp;page_size=20)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;res:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;共检索商品{res[&amp;#39;total&amp;#39;]}件，有效在售商品：{len(res[&amp;#39;goods&amp;#39;])}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;goods&amp;nbsp;in&amp;nbsp;res[&amp;quot;goods&amp;quot;]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(goods[&amp;quot;goodsId&amp;quot;],&amp;nbsp;goods[&amp;quot;title&amp;quot;],&amp;nbsp;goods[&amp;quot;price&amp;quot;])&lt;/pre&gt;&lt;/div&gt;&lt;p data-pid=&quot;XsyOO6Nv&quot;&gt;代码核心思路解析&lt;/p&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;签名封装：独立抽离签名生成函数，每次请求携带实时时间戳，防止签名过期。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;数据前置过滤：接口返回原始数据混杂下架、零库存商品，在接口层直接过滤，减少上层业务处理压力。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Session 复用：复用 http 连接，减少频繁建立连接带来的性能损耗，适合循环分页拉取。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;p data-pid=&quot;jlU79b3C&quot;&gt;线上对接避坑要点&lt;/p&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;限流控制：平台接口存在 QPS 限制，分页循环抓取时，每页请求建议增加 1~2 秒延时，高频请求会触发临时封禁。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;分页终止判断：不能单纯循环到设定页数，需要通过返回 total 和当前页商品数量判断是否到达最后一页，避免无效请求。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;关键词编码：中文关键词接口会自动处理编码，但特殊符号、emoji 建议提前清洗，防止参数解析报错。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;字段兼容：不同品类商品返回字段存在差异，读取字段时优先使用&lt;code&gt;.get()&lt;/code&gt;方式，避免 KeyError 程序崩溃。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Sat, 10 Oct 2026 14:29:16 +0800</pubDate></item><item><title>义乌购商品 ID 查询详情接口实战：批发类商品多规格数据归一化方案</title><link>https://apiproxylog.com/?id=248</link><description>&lt;p&gt;&lt;span id=&quot;content&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;HZdh7EQ3&quot;&gt;前言&lt;/p&gt;&lt;p data-pid=&quot;M43nIsrJ&quot;&gt;义乌购作为小商品 B2B 批发平台，商品详情存在多 SKU 区间价、起批量、档口信息等特有字段，和零售电商结构差异很大。常规接口调用 Demo 大多只做简单请求打印，忽略批发业务核心的数据规整。本文从业务落地角度，封装根据商品 ID 拉取详情的调用类，重点解决多规格价格扁平化、空字段兼容、请求异常重试，适配进销存、比价系统的数据同步场景。&lt;/p&gt;&lt;p data-pid=&quot;CXHuPPyG&quot;&gt;前置准备&lt;/p&gt;&lt;p data-pid=&quot;b_REhzzi&quot;&gt;开发环境：Python3.8+，依赖 requests 库。调用前需要平台接口访问凭证，接口请求需要携带 token 做身份校验，接口入参核心为商品唯一 ID。批发商品存在阶梯价格、最小起订量，返回 JSON 结构嵌套层级深，直接解析容易出现键不存在导致程序崩溃。&lt;/p&gt;&lt;figure data-size=&quot;normal&quot;&gt;&lt;div class=&quot;RichText-ConditionalImagePortal&quot;&gt;&lt;img src=&quot;https://pic1.zhimg.com/80/v2-aaf6b0ea3d39085c8508c8520217194c_720w.webp&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1153&quot; data-rawheight=&quot;576&quot; data-original-token=&quot;v2-f04dace6620fcd14312224a57c28abab&quot; class=&quot;origin_image zh-lightbox-thumb lazy&quot; width=&quot;1153&quot; data-original=&quot;https://pic1.zhimg.com/v2-aaf6b0ea3d39085c8508c8520217194c_r.jpg&quot; data-actualsrc=&quot;https://pic1.zhimg.com/v2-aaf6b0ea3d39085c8508c8520217194c_1440w.jpg&quot; height=&quot;576&quot; data-lazy-status=&quot;ok&quot;/&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p data-pid=&quot;Sjs9rPUr&quot;&gt;&lt;a href=&quot;https://o0b.cn/iiiace&quot; target=&quot;_blank&quot;&gt;点击获取key和secret&lt;/a&gt;&lt;/p&gt;&lt;p data-pid=&quot;AyMtK1EX&quot;&gt;完整代码示例&lt;/p&gt;&lt;p data-pid=&quot;A7dZB_SW&quot;&gt;python&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;import&amp;nbsp;requests
import&amp;nbsp;time

class&amp;nbsp;YiwugoDetailApi:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;token:&amp;nbsp;str):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.token&amp;nbsp;=&amp;nbsp;token
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.base_url&amp;nbsp;=&amp;nbsp;&amp;quot;https://api.yiwugo.com/goods/detail&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.session&amp;nbsp;=&amp;nbsp;requests.Session()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.session.headers.update({
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;User-Agent&amp;quot;:&amp;nbsp;&amp;quot;Mozilla/5.0&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;Authorization&amp;quot;:&amp;nbsp;f&amp;quot;Bearer&amp;nbsp;{self.token}&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;})

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_detail_by_id(self,&amp;nbsp;goods_id:&amp;nbsp;str,&amp;nbsp;retry=2):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;根据商品ID获取详情，自动重试，清洗批发规格数据&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;params&amp;nbsp;=&amp;nbsp;{&amp;quot;goodsId&amp;quot;:&amp;nbsp;goods_id}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;_&amp;nbsp;in&amp;nbsp;range(retry):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resp&amp;nbsp;=&amp;nbsp;self.session.get(self.base_url,&amp;nbsp;params=params,&amp;nbsp;timeout=10)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resp.raise_for_status()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;res_data&amp;nbsp;=&amp;nbsp;resp.json()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;res_data.get(&amp;quot;code&amp;quot;)&amp;nbsp;!=&amp;nbsp;200:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;status&amp;quot;:&amp;nbsp;False,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;res_data.get(&amp;quot;msg&amp;quot;),&amp;nbsp;&amp;quot;data&amp;quot;:&amp;nbsp;None}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw&amp;nbsp;=&amp;nbsp;res_data[&amp;quot;data&amp;quot;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;批发数据扁平化处理
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;goods_id&amp;quot;:&amp;nbsp;raw.get(&amp;quot;goodsId&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;raw.get(&amp;quot;title&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;shop_name&amp;quot;:&amp;nbsp;raw.get(&amp;quot;shopName&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;min_order&amp;quot;:&amp;nbsp;raw.get(&amp;quot;minOrderNum&amp;quot;),&amp;nbsp;#最小起订
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;price_list&amp;quot;:&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku_list&amp;nbsp;=&amp;nbsp;raw.get(&amp;quot;skuList&amp;quot;,&amp;nbsp;[])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;sku&amp;nbsp;in&amp;nbsp;sku_list:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result[&amp;quot;price_list&amp;quot;].append({
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;spec_name&amp;quot;:&amp;nbsp;sku.get(&amp;quot;specName&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;sku.get(&amp;quot;price&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;stock&amp;quot;:&amp;nbsp;sku.get(&amp;quot;stockNum&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;status&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;&amp;quot;success&amp;quot;,&amp;nbsp;&amp;quot;data&amp;quot;:&amp;nbsp;result}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception&amp;nbsp;as&amp;nbsp;e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;time.sleep(1)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;status&amp;quot;:&amp;nbsp;False,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;&amp;quot;请求超时/接口异常&amp;quot;,&amp;nbsp;&amp;quot;data&amp;quot;:&amp;nbsp;None}

if&amp;nbsp;__name__&amp;nbsp;==&amp;nbsp;&amp;quot;__main__&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;api&amp;nbsp;=&amp;nbsp;YiwugoDetailApi(token=&amp;quot;你的访问凭证&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ret&amp;nbsp;=&amp;nbsp;api.get_detail_by_id(goods_id=&amp;quot;YI20250612001&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(ret)&lt;/pre&gt;&lt;/div&gt;&lt;p data-pid=&quot;CaJSyWhu&quot;&gt;代码核心解析&lt;/p&gt;&lt;p data-pid=&quot;b2Q0m2KS&quot;&gt;封装类采用 Session 复用连接，减少 TCP 握手开销。核心逻辑不是单纯打印原始返回值，而是对 B2B 批发字段做扁平化处理，提取标题、店铺、起订量、SKU 规格库存价格。增加重试机制，应对平台接口瞬时限流。很多小商品 SKU 数量多、部分规格库存为 0，代码自动兼容空数组，避免 KeyError 中断任务。&lt;/p&gt;&lt;p data-pid=&quot;1c5OoUGG&quot;&gt;踩坑总结&lt;/p&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;阶梯批发价不是单一售价，必须遍历 skuList，业务入库不能只取第一条价格；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;部分下架商品 ID 仍能请求，但 data 内字段为空，业务层需要增加在售状态判断；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;接口有访问频率限制，批量轮询时必须增加延时，短时间高频请求会触发 token 拦截；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;档口地址、发货时效字段存在部分商品缺失，解析时统一使用 get 方式获取。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Fri, 09 Oct 2026 17:40:01 +0800</pubDate></item><item><title>义乌购关键词商品列表接口实战：批发起订量字段适配与分页降噪方案</title><link>https://apiproxylog.com/?id=247</link><description>&lt;p&gt;&lt;span id=&quot;content&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;rOX5nDLQ&quot;&gt;前言&lt;/p&gt;&lt;p data-pid=&quot;F32OOxx8&quot;&gt;义乌购作为小商品批发平台，和零售电商搜索接口最大差异在于&lt;strong&gt;起订量、档口门店、多阶梯报价&lt;/strong&gt;这三类批发专属字段。常规搜索接口 demo 大多只获取标题与售价，忽略批发业务字段解析，直接使用会导致采购比价系统数据失真。本文从批发业务视角，封装关键词商品列表请求，增加阶梯价格解析、最小起订过滤、重复商品降噪逻辑，适合采购选品、行情监控场景。&lt;/p&gt;&lt;p data-pid=&quot;lt6brokD&quot;&gt;前置准备&lt;/p&gt;&lt;p data-pid=&quot;R3foq81W&quot;&gt;调用前需要在开放平台申请&lt;code&gt;key&lt;/code&gt;与&lt;code&gt;secret&lt;/code&gt;密钥，接口采用 GET 请求，返回 JSON 结构。重点关注：义乌购搜索结果存在&lt;strong&gt;同商品多档口重复铺货&lt;/strong&gt;，需要在业务层做数据去重；价格字段不是单一零售价，会附带起批量，必须单独解析。&lt;/p&gt;&lt;figure data-size=&quot;normal&quot;&gt;&lt;div class=&quot;RichText-ConditionalImagePortal&quot;&gt;&lt;img src=&quot;https://pica.zhimg.com/80/v2-612393a4a1b7327ed28ba4105d96b3ce_720w.jpg&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1161&quot; data-rawheight=&quot;588&quot; data-original-token=&quot;v2-bc5f14de5948cda3cd94a9c883544a9f&quot; class=&quot;origin_image zh-lightbox-thumb lazy&quot; width=&quot;1161&quot; data-original=&quot;https://pica.zhimg.com/v2-612393a4a1b7327ed28ba4105d96b3ce_r.jpg&quot; data-actualsrc=&quot;https://pica.zhimg.com/v2-612393a4a1b7327ed28ba4105d96b3ce_1440w.jpg&quot; height=&quot;588&quot; data-lazy-status=&quot;ok&quot;/&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p data-pid=&quot;prLcEeYE&quot;&gt;&lt;a href=&quot;https://o0b.cn/iiiace&quot; target=&quot;_blank&quot;&gt;点击获取key和secret&lt;/a&gt;&lt;/p&gt;&lt;p data-pid=&quot;oDNeYJW4&quot;&gt;核心代码实现&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;import&amp;nbsp;requests
import&amp;nbsp;json

class&amp;nbsp;YiwugoSearch:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;key,&amp;nbsp;secret):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.key&amp;nbsp;=&amp;nbsp;key
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.secret&amp;nbsp;=&amp;nbsp;secret
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.api_url&amp;nbsp;=&amp;nbsp;&amp;quot;https://api-gw.onebound.cn/yiwugo/item_search&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.session&amp;nbsp;=&amp;nbsp;requests.Session()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;search_items(self,&amp;nbsp;keyword,&amp;nbsp;page=1,&amp;nbsp;min_order=1):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;params&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;key&amp;quot;:&amp;nbsp;self.key,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;secret&amp;quot;:&amp;nbsp;self.secret,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;api_name&amp;quot;:&amp;nbsp;&amp;quot;item_search&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;q&amp;quot;:&amp;nbsp;keyword,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;page&amp;quot;:&amp;nbsp;page,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;result_type&amp;quot;:&amp;nbsp;&amp;quot;json&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;cache&amp;quot;:&amp;nbsp;&amp;quot;no&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resp&amp;nbsp;=&amp;nbsp;self.session.get(self.api_url,&amp;nbsp;params=params,&amp;nbsp;timeout=15)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;res_data&amp;nbsp;=&amp;nbsp;resp.json()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;item_list&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;res_data.get(&amp;quot;status&amp;quot;)&amp;nbsp;!=&amp;nbsp;200:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;接口请求异常：&amp;quot;,&amp;nbsp;res_data.get(&amp;quot;msg&amp;quot;))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;遍历商品，过滤低于最小起订量的商品
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;item&amp;nbsp;in&amp;nbsp;res_data[&amp;quot;data&amp;quot;][&amp;quot;items&amp;quot;]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;int(item.get(&amp;quot;min_order&amp;quot;,&amp;nbsp;0))&amp;nbsp;&amp;gt;=&amp;nbsp;min_order:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;goods&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;item_id&amp;quot;:&amp;nbsp;item[&amp;quot;num_iid&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;item[&amp;quot;title&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;item[&amp;quot;price&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;min_order&amp;quot;:&amp;nbsp;item[&amp;quot;min_order&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;shop_name&amp;quot;:&amp;nbsp;item[&amp;quot;shop&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;market_addr&amp;quot;:&amp;nbsp;item[&amp;quot;market_address&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;pic_url&amp;quot;:&amp;nbsp;item[&amp;quot;pic_url&amp;quot;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;item_list.append(goods)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;简单去重，按商品ID去重
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;unique_items&amp;nbsp;=&amp;nbsp;list({v[&amp;quot;item_id&amp;quot;]:v&amp;nbsp;for&amp;nbsp;v&amp;nbsp;in&amp;nbsp;item_list}.values())
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;unique_items

if&amp;nbsp;__name__&amp;nbsp;==&amp;nbsp;&amp;quot;__main__&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;替换为自己的密钥
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;client&amp;nbsp;=&amp;nbsp;YiwugoSearch(key=&amp;quot;your_key&amp;quot;,&amp;nbsp;secret=&amp;quot;your_secret&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;client.search_items(keyword=&amp;quot;亚克力饰品&amp;quot;,&amp;nbsp;page=1,&amp;nbsp;min_order=100)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(json.dumps(result,&amp;nbsp;ensure_ascii=False,&amp;nbsp;indent=2))&lt;/pre&gt;&lt;/div&gt;&lt;p data-pid=&quot;KBvgJ72B&quot;&gt;代码逻辑解析&lt;/p&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;封装请求会话，复用连接减少 TCP 握手开销，设置超时防止长时间阻塞。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;入参增加&lt;code&gt;min_order&lt;/code&gt;，可以按业务需求过滤起订门槛过高的商品，适配小批量采购场景。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;提取批发特有字段：档口市场地址、最小起订量，不再只拿基础标题价格。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;使用字典推导式基于商品 ID 去重，解决多店铺同款商品重复返回的问题。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;p data-pid=&quot;lr5hM8bx&quot;&gt;踩坑要点&lt;/p&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;关键词编码：中文关键词会自动 urlencode，不要手动二次编码，否则出现检索为空。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;限流策略：接口有 QPS 限制，批量分页轮询时，每页请求增加休眠，短时间高频调用会触发 429 限流。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;阶梯价格：返回 price 字段为基础单价，如需多档报价，需要结合商品详情接口补充。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;缓存开关：调试阶段 cache 设置 no 获取实时数据；生产环境开启缓存，降低接口消耗。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Thu, 08 Oct 2026 16:49:46 +0800</pubDate></item><item><title>17 货源 (gz.17zwd.com) 商品详情接口：服装档口规格扁平化与货源元数据解析方案</title><link>https://apiproxylog.com/?id=246</link><description>&lt;p&gt;&lt;span id=&quot;content&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;bzsNP1Ye&quot;&gt;前言&lt;/p&gt;&lt;p data-pid=&quot;0EXC7kR6&quot;&gt;17 货源（&lt;a href=&quot;https://link.zhihu.com/?target=https%3A//link.wtturl.cn/%3Ftarget%3Dhttps%253A%252F%252Fgz.17zwd.com%26scene%3Dim%26aid%3D582478%26lang%3Dzh&quot; data-draft-type=&quot;text-link&quot; class=&quot; wrap external&quot; target=&quot;_blank&quot; rel=&quot;nofollow noreferrer&quot; data-za-detail-view-id=&quot;1043&quot;&gt;gz.17zwd.com&lt;/a&gt;）作为广州沙河、十三行服装批发 B2B 平台，商品详情接口除基础图文之外，还包含档口摊位、拿货规则、多尺码 SKU、面料材质等服装供应链特有的元数据。网上大多示例只做简单 http 请求，忽略该平台痛点：SKU 规格嵌套层级不固定、档口信息字段分散、起批规则多样、下架商品依旧返回部分基础字段。本文不再演示基础调用，聚焦&lt;strong&gt;规格扁平化解析、档口货源元数据提取、无效商品状态识别&lt;/strong&gt;，适配服装 ERP 货源同步业务。&lt;/p&gt;&lt;p data-pid=&quot;TKjHwOYe&quot;&gt;对接前需要在开放后台申请&lt;code&gt;app_key&lt;/code&gt;、&lt;code&gt;app_secret&lt;/code&gt;，接口需要 MD5 签名鉴权，入参为商品 goods_id，返回包含图文、多 SKU、批发市场档口信息。&lt;/p&gt;&lt;figure data-size=&quot;normal&quot;&gt;&lt;div class=&quot;RichText-ConditionalImagePortal&quot;&gt;&lt;img src=&quot;https://pica.zhimg.com/80/v2-1026429c71436513e84ca4acb8158174_720w.webp&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1165&quot; data-rawheight=&quot;576&quot; data-original-token=&quot;v2-2a59c03bbcac238acdd86d81e4a95cde&quot; class=&quot;origin_image zh-lightbox-thumb lazy&quot; width=&quot;1165&quot; data-original=&quot;https://pica.zhimg.com/v2-1026429c71436513e84ca4acb8158174_r.jpg&quot; data-actualsrc=&quot;https://pica.zhimg.com/v2-1026429c71436513e84ca4acb8158174_1440w.jpg&quot; height=&quot;576&quot; data-lazy-status=&quot;ok&quot;/&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p data-pid=&quot;cfVf7vAd&quot;&gt;&lt;a href=&quot;https://o0b.cn/iiiace&quot; target=&quot;_blank&quot;&gt;点击获取key和secret&lt;/a&gt;&lt;/p&gt;&lt;p data-pid=&quot;dA6Dq8Cr&quot;&gt;完整代码示例&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;import&amp;nbsp;requests
import&amp;nbsp;time
import&amp;nbsp;hashlib

class&amp;nbsp;SeventeenZwdDetail:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;app_key,&amp;nbsp;app_secret):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.app_key&amp;nbsp;=&amp;nbsp;app_key
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.app_secret&amp;nbsp;=&amp;nbsp;app_secret
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.api_url&amp;nbsp;=&amp;nbsp;&amp;quot;https://open.17zwd.com/api/goods/detail&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.session&amp;nbsp;=&amp;nbsp;requests.Session()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;build_sign(self,&amp;nbsp;params):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;参数字典排序生成md5签名&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sorted_items&amp;nbsp;=&amp;nbsp;sorted(params.items())
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw_str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;.join([f&amp;quot;{k}{v}&amp;quot;&amp;nbsp;for&amp;nbsp;k,&amp;nbsp;v&amp;nbsp;in&amp;nbsp;sorted_items])&amp;nbsp;+&amp;nbsp;self.app_secret
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;hashlib.md5(raw_str.encode(&amp;quot;utf‑8&amp;quot;)).hexdigest().upper()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_goods_detail(self,&amp;nbsp;goods_id,&amp;nbsp;site=&amp;quot;gz&amp;quot;):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;params&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;app_key&amp;quot;:&amp;nbsp;self.app_key,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;site&amp;quot;:&amp;nbsp;site,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;goods_id&amp;quot;:&amp;nbsp;goods_id,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;timestamp&amp;quot;:&amp;nbsp;str(int(time.time()))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;params[&amp;quot;sign&amp;quot;]&amp;nbsp;=&amp;nbsp;self.build_sign(params)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resp&amp;nbsp;=&amp;nbsp;self.session.get(self.api_url,&amp;nbsp;params=params,&amp;nbsp;timeout=16)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resp.raise_for_status()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resp_json&amp;nbsp;=&amp;nbsp;resp.json()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception&amp;nbsp;as&amp;nbsp;e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;ok&amp;quot;:False,&amp;nbsp;&amp;quot;msg&amp;quot;:f&amp;quot;网络异常:{str(e)}&amp;quot;,&amp;nbsp;&amp;quot;data&amp;quot;:None}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;resp_json.get(&amp;quot;code&amp;quot;)&amp;nbsp;!=&amp;nbsp;200:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;ok&amp;quot;:False,&amp;nbsp;&amp;quot;msg&amp;quot;:resp_json.get(&amp;quot;msg&amp;quot;,&amp;quot;接口业务异常&amp;quot;),&amp;nbsp;&amp;quot;data&amp;quot;:None}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw&amp;nbsp;=&amp;nbsp;resp_json.get(&amp;quot;data&amp;quot;,{})

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#规格扁平化处理，把嵌套SKU展开成一维数组
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku_list&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;sku&amp;nbsp;in&amp;nbsp;raw.get(&amp;quot;sku_list&amp;quot;,[]):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku_list.append({
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;spec_name&amp;quot;:sku.get(&amp;quot;spec_name&amp;quot;,&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;wholesale_price&amp;quot;:float(sku.get(&amp;quot;wholesale_price&amp;quot;,0)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;stock_num&amp;quot;:sku.get(&amp;quot;stock_num&amp;quot;,0),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;spec_code&amp;quot;:sku.get(&amp;quot;spec_code&amp;quot;,&amp;quot;&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;})

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result_data&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;goods_id&amp;quot;:raw.get(&amp;quot;goods_id&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;title&amp;quot;:raw.get(&amp;quot;title&amp;quot;,&amp;quot;&amp;quot;).strip(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;goods_sn&amp;quot;:raw.get(&amp;quot;goods_sn&amp;quot;,&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;market_name&amp;quot;:raw.get(&amp;quot;market_name&amp;quot;,&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;stall_name&amp;quot;:raw.get(&amp;quot;stall_name&amp;quot;,&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;stall_no&amp;quot;:raw.get(&amp;quot;stall_no&amp;quot;,&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;min_batch&amp;quot;:raw.get(&amp;quot;min_batch&amp;quot;,1),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;batch_type&amp;quot;:raw.get(&amp;quot;batch_type&amp;quot;,&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;material&amp;quot;:raw.get(&amp;quot;material&amp;quot;,&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;images&amp;quot;:[img.get(&amp;quot;url&amp;quot;,&amp;quot;&amp;quot;)&amp;nbsp;for&amp;nbsp;img&amp;nbsp;in&amp;nbsp;raw.get(&amp;quot;images&amp;quot;,[])],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;desc&amp;quot;:raw.get(&amp;quot;desc&amp;quot;,&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sku_list&amp;quot;:sku_list,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;is_on_sale&amp;quot;:bool(raw.get(&amp;quot;is_on_sale&amp;quot;,0))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#过滤已经下架商品
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;result_data[&amp;quot;is_on_sale&amp;quot;]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;ok&amp;quot;:False,&amp;quot;msg&amp;quot;:&amp;quot;商品已下架&amp;quot;,&amp;quot;data&amp;quot;:result_data}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;ok&amp;quot;:True,&amp;quot;data&amp;quot;:result_data}

if&amp;nbsp;__name__&amp;nbsp;==&amp;nbsp;&amp;quot;__main__&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;client&amp;nbsp;=&amp;nbsp;SeventeenZwdDetail(&amp;quot;your_app_key&amp;quot;,&amp;quot;your_app_secret&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ret&amp;nbsp;=&amp;nbsp;client.get_goods_detail(goods_id=&amp;quot;12345678&amp;quot;,site=&amp;quot;gz&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(ret[&amp;quot;data&amp;quot;])&lt;/pre&gt;&lt;/div&gt;&lt;p data-pid=&quot;jcROTvFt&quot;&gt;核心差异化设计思路&lt;/p&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;SKU 规格扁平化&lt;/strong&gt;：针对服装多颜色多尺码嵌套结构，把多层 sku_list 拆解为一维数组，方便直接入库，避免业务层反复嵌套循环解析。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;B2B 货源元数据提取&lt;/strong&gt;：专门解析批发市场、档口摊位、起批模式、面料材质，这是服装批发业务核心信息，区别普通电商只解析图文价格。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;在售状态强校验&lt;/strong&gt;：下架商品接口不会直接报错，通过&lt;code&gt;is_on_sale&lt;/code&gt;字段主动识别，做业务标记，避免把已经停售的货源同步到业务系统。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;安全取值容错&lt;/strong&gt;：所有字段均使用 get 安全取值，不同品类（女装、男装、家居服）返回字段存在差异，防止个别字段缺失直接抛出异常。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Wed, 30 Sep 2026 17:08:45 +0800</pubDate></item><item><title>17 货源 关键词商品列表接口：档口货源字段归一化与分页漂移处理方案</title><link>https://apiproxylog.com/?id=245</link><description>&lt;p&gt;&lt;span id=&quot;content&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;iWt6j_lS&quot;&gt;前言&lt;/p&gt;&lt;p data-pid=&quot;1yVKD2iF&quot;&gt;17 货源（一起做网店）是广州沙河、十三行等服装批发市场线上 B2B 货源平台，关键词商品列表接口常用于服装选品、档口货源监控、款号比价业务。网上多数示例只做简单请求演示，忽略该平台业务特征：返回数据包含档口市场摊位信息、起批门槛、多档口同款重复铺货、高页码分页漂移、部分字段动态缺失。本文跳出基础调用 Demo，聚焦&lt;strong&gt;货源业务字段提取、同款商品去重、分页边界校验、异常数据过滤&lt;/strong&gt;，提供面向生产同步的封装方案。&lt;/p&gt;&lt;p data-pid=&quot;U3dMX9Z7&quot;&gt;对接前需要在平台开发者后台申请&lt;code&gt;app_key&lt;/code&gt;与&lt;code&gt;app_secret&lt;/code&gt;接口凭证，接口返回包含商品货号、批发价、起批量、所属批发市场、档口摊位等服装 B2B 特有的字段一起做网店。&lt;/p&gt;&lt;figure data-size=&quot;normal&quot;&gt;&lt;div class=&quot;RichText-ConditionalImagePortal&quot;&gt;&lt;img src=&quot;https://pica.zhimg.com/80/v2-1ad093f24e0b64a6eca68fb61cdea790_720w.jpg&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1190&quot; data-rawheight=&quot;695&quot; data-original-token=&quot;v2-2cfbb7c68b135708433387b64bb5bb47&quot; class=&quot;origin_image zh-lightbox-thumb lazy&quot; width=&quot;1190&quot; data-original=&quot;https://pica.zhimg.com/v2-1ad093f24e0b64a6eca68fb61cdea790_r.jpg&quot; data-actualsrc=&quot;https://pica.zhimg.com/v2-1ad093f24e0b64a6eca68fb61cdea790_1440w.jpg&quot; height=&quot;695&quot; data-lazy-status=&quot;ok&quot;/&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p data-pid=&quot;bhcDoHDE&quot;&gt;&lt;a href=&quot;https://o0b.cn/iiiace&quot; target=&quot;_blank&quot;&gt;点击获取key和secret&lt;/a&gt;&lt;/p&gt;&lt;p data-pid=&quot;2XRIPWLa&quot;&gt;完整代码示例&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;import&amp;nbsp;requests
import&amp;nbsp;time
import&amp;nbsp;hashlib

class&amp;nbsp;SeventeenZwdSearch:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;app_key,&amp;nbsp;app_secret):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.app_key&amp;nbsp;=&amp;nbsp;app_key
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.app_secret&amp;nbsp;=&amp;nbsp;app_secret
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.api_url&amp;nbsp;=&amp;nbsp;&amp;quot;https://open.17zwd.com/api/goods/search&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.session&amp;nbsp;=&amp;nbsp;requests.Session()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.seen_goods&amp;nbsp;=&amp;nbsp;set()&amp;nbsp;#&amp;nbsp;全局去重，过滤多档口同款
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.page_sleep&amp;nbsp;=&amp;nbsp;0.6

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;build_sign(self,&amp;nbsp;params):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;按照平台规则生成md5签名&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sorted_items&amp;nbsp;=&amp;nbsp;sorted(params.items())
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw_str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;.join([f&amp;quot;{k}{v}&amp;quot;&amp;nbsp;for&amp;nbsp;k,&amp;nbsp;v&amp;nbsp;in&amp;nbsp;sorted_items])&amp;nbsp;+&amp;nbsp;self.app_secret
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;hashlib.md5(raw_str.encode(&amp;quot;utf‑8&amp;quot;)).hexdigest().upper()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;keyword_search(self,&amp;nbsp;keyword,&amp;nbsp;site=&amp;quot;gz&amp;quot;,&amp;nbsp;page=1,&amp;nbsp;page_size=20):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;前置参数拦截，平台限制单页最大50条
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;page&amp;nbsp;&amp;lt;&amp;nbsp;1&amp;nbsp;or&amp;nbsp;page_size&amp;nbsp;&amp;gt;&amp;nbsp;50:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;ok&amp;quot;:False,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;quot;分页参数非法&amp;quot;,&amp;nbsp;&amp;quot;data&amp;quot;:[]}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;params&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;app_key&amp;quot;:&amp;nbsp;self.app_key,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;site&amp;quot;:&amp;nbsp;site,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;keyword&amp;quot;:&amp;nbsp;keyword,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;page&amp;quot;:&amp;nbsp;page,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;page_size&amp;quot;:&amp;nbsp;page_size,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;timestamp&amp;quot;:&amp;nbsp;str(int(time.time()))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;params[&amp;quot;sign&amp;quot;]&amp;nbsp;=&amp;nbsp;self.build_sign(params)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resp&amp;nbsp;=&amp;nbsp;self.session.get(self.api_url,&amp;nbsp;params=params,&amp;nbsp;timeout=16)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resp.raise_for_status()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resp_json&amp;nbsp;=&amp;nbsp;resp.json()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception&amp;nbsp;as&amp;nbsp;e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;ok&amp;quot;:False,&amp;nbsp;&amp;quot;msg&amp;quot;:f&amp;quot;网络异常:{str(e)}&amp;quot;,&amp;nbsp;&amp;quot;data&amp;quot;:[]}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;resp_json.get(&amp;quot;code&amp;quot;)&amp;nbsp;!=&amp;nbsp;200:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;ok&amp;quot;:False,&amp;nbsp;&amp;quot;msg&amp;quot;:resp_json.get(&amp;quot;msg&amp;quot;,&amp;quot;接口业务异常&amp;quot;),&amp;nbsp;&amp;quot;data&amp;quot;:[]}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw_list&amp;nbsp;=&amp;nbsp;resp_json.get(&amp;quot;data&amp;quot;,{}).get(&amp;quot;list&amp;quot;,[])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;clean_result&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;item&amp;nbsp;in&amp;nbsp;raw_list:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;goods_id&amp;nbsp;=&amp;nbsp;item.get(&amp;quot;goods_id&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;去重&amp;nbsp;+&amp;nbsp;过滤无效无批发价商品
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;goods_id&amp;nbsp;or&amp;nbsp;goods_id&amp;nbsp;in&amp;nbsp;self.seen_goods&amp;nbsp;or&amp;nbsp;float(item.get(&amp;quot;wholesale_price&amp;quot;,0))&amp;nbsp;&amp;lt;=&amp;nbsp;0:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;continue
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.seen_goods.add(goods_id)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;clean_result.append({
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;goods_id&amp;quot;:&amp;nbsp;goods_id,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;item.get(&amp;quot;title&amp;quot;,&amp;quot;&amp;quot;).strip(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;goods_sn&amp;quot;:&amp;nbsp;item.get(&amp;quot;goods_sn&amp;quot;,&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;wholesale_price&amp;quot;:&amp;nbsp;float(item.get(&amp;quot;wholesale_price&amp;quot;,0)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;min_batch&amp;quot;:&amp;nbsp;item.get(&amp;quot;min_batch&amp;quot;,1),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;shop_name&amp;quot;:&amp;nbsp;item.get(&amp;quot;shop_name&amp;quot;,&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;market_name&amp;quot;:&amp;nbsp;item.get(&amp;quot;market_name&amp;quot;,&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;stall_no&amp;quot;:&amp;nbsp;item.get(&amp;quot;stall_no&amp;quot;,&amp;quot;&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;time.sleep(self.page_sleep)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;ok&amp;quot;:&amp;nbsp;True,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;total&amp;quot;:&amp;nbsp;resp_json.get(&amp;quot;data&amp;quot;,{}).get(&amp;quot;total&amp;quot;,0),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;data&amp;quot;:&amp;nbsp;clean_result
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

if&amp;nbsp;__name__&amp;nbsp;==&amp;nbsp;&amp;quot;__main__&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;client&amp;nbsp;=&amp;nbsp;SeventeenZwdSearch(&amp;quot;your_app_key&amp;quot;,&amp;quot;your_app_secret&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ret&amp;nbsp;=&amp;nbsp;client.keyword_search(keyword=&amp;quot;牛仔阔腿裤&amp;quot;,&amp;nbsp;site=&amp;quot;gz&amp;quot;,&amp;nbsp;page=1)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;清洗后货源列表：&amp;quot;,&amp;nbsp;ret[&amp;quot;data&amp;quot;])&lt;/pre&gt;&lt;/div&gt;&lt;p data-pid=&quot;E4S17sPa&quot;&gt;核心差异化设计思路&lt;/p&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;B2B 货源定向解析&lt;/strong&gt;：专门提取批发价、起批量、批发市场、档口摊位，这些是服装货源业务核心字段，区别普通电商只取标题价格。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;同款货源内存去重&lt;/strong&gt;：平台不同档口会铺货同款，利用&lt;code&gt;goods_id&lt;/code&gt;集合做全局去重，避免统计重复款式。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;分页参数强校验&lt;/strong&gt;：拦截非法页码、超最大单页条数，规避深度分页返回漂移错乱数据。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;脏货源过滤&lt;/strong&gt;：自动剔除批发价为空、无效占位商品，减少后续人工筛选成本。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;p data-pid=&quot;3A__Xuu1&quot;&gt;线上对接避坑要点&lt;/p&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;站点参数&lt;code&gt;site&lt;/code&gt;：&lt;code&gt;gz&lt;/code&gt;代表广州站，支持杭州、普宁等多个站点切换，检索广州货源必须传入 gz 参数一起做网店。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;深度分页问题：高页码会出现商品重复、顺序错乱，业务不要无脑循环拉取全部 total，建议限定前 20 页。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;调用频率：接口 QPS 不宜过高，批量采集每页必须增加延时，高频请求会临时封禁密钥权限。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;签名注意：所有非空公共参数都参与签名，时间戳为秒级时间戳，时间偏差过大会鉴权失败。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Tue, 29 Sep 2026 17:24:46 +0800</pubDate></item><item><title>搜好货平台关键词商品搜索接口：分页容错与商品数据轻量化提取方案</title><link>https://apiproxylog.com/?id=244</link><description>&lt;p&gt;&lt;span id=&quot;content&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;UYhmXBgx&quot;&gt;前言&lt;/p&gt;&lt;p data-pid=&quot;I6-oiZBu&quot;&gt;搜好货作为 B2B 货源平台，很多业务场景需要根据关键词批量检索货源商品。网上大多示例仅实现基础请求调用，缺少对接口分页异常、空页截断、多规格冗余字段过滤的处理。本文从业务落地角度，封装一套具备自动重试、结果去重、字段裁剪的调用示例，适用于货源比价、商品监控等场景。&lt;/p&gt;&lt;p data-pid=&quot;k-kzp-3D&quot;&gt;前置准备&lt;/p&gt;&lt;p data-pid=&quot;VcCIS-Ok&quot;&gt;对接前需要准备平台开放接口凭证，包括 AppKey、AppSecret，申请对应搜索接口权限。接口调用遵循签名机制，请求参数需要按规则生成 sign 签名，同时平台存在调用频次限制，短时间高频请求会触发限流，代码内置简易限流控制。&lt;/p&gt;&lt;figure data-size=&quot;normal&quot;&gt;&lt;div class=&quot;RichText-ConditionalImagePortal&quot;&gt;&lt;img src=&quot;https://pic1.zhimg.com/80/v2-633753053d0dbe5a174ce3c5afe034c8_720w.webp&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1169&quot; data-rawheight=&quot;577&quot; data-original-token=&quot;v2-a03ecfae053a1fe2f2f81998408863fb&quot; class=&quot;origin_image zh-lightbox-thumb lazy&quot; width=&quot;1169&quot; data-original=&quot;https://pic1.zhimg.com/v2-633753053d0dbe5a174ce3c5afe034c8_r.jpg&quot; data-actualsrc=&quot;https://pic1.zhimg.com/v2-633753053d0dbe5a174ce3c5afe034c8_1440w.jpg&quot; height=&quot;577&quot; data-lazy-status=&quot;ok&quot;/&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p data-pid=&quot;raJEXYhO&quot;&gt;&lt;a href=&quot;https://o0b.cn/iiiace&quot; target=&quot;_blank&quot;&gt;点击获取key和secret&lt;/a&gt;&lt;/p&gt;&lt;p data-pid=&quot;rkSFlK2s&quot;&gt;核心代码示例&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;import&amp;nbsp;requests
import&amp;nbsp;time
import&amp;nbsp;hashlib

class&amp;nbsp;SouhaohuoSearch:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;app_key,&amp;nbsp;app_secret):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.app_key&amp;nbsp;=&amp;nbsp;app_key
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.app_secret&amp;nbsp;=&amp;nbsp;app_secret
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.api_url&amp;nbsp;=&amp;nbsp;&amp;quot;https://api.souhaohuo.com/goods/search&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.session&amp;nbsp;=&amp;nbsp;requests.Session()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.session.headers.update({&amp;quot;User-Agent&amp;quot;:&amp;nbsp;&amp;quot;api-client/1.0&amp;quot;})

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;build_sign(self,&amp;nbsp;params):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sorted_items&amp;nbsp;=&amp;nbsp;sorted(params.items())
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw_str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;.join([f&amp;quot;{k}{v}&amp;quot;&amp;nbsp;for&amp;nbsp;k,&amp;nbsp;v&amp;nbsp;in&amp;nbsp;sorted_items])&amp;nbsp;+&amp;nbsp;self.app_secret
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;hashlib.md5(raw_str.encode(&amp;quot;utf-8&amp;quot;)).hexdigest().upper()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;search_goods(self,&amp;nbsp;keyword,&amp;nbsp;page=1,&amp;nbsp;page_size=20):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;params&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;app_key&amp;quot;:&amp;nbsp;self.app_key,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;keyword&amp;quot;:&amp;nbsp;keyword,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;page&amp;quot;:&amp;nbsp;page,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;page_size&amp;quot;:&amp;nbsp;page_size,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;timestamp&amp;quot;:&amp;nbsp;str(int(time.time()))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;params[&amp;quot;sign&amp;quot;]&amp;nbsp;=&amp;nbsp;self.build_sign(params)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resp&amp;nbsp;=&amp;nbsp;self.session.get(self.api_url,&amp;nbsp;params=params,&amp;nbsp;timeout=10)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;res_data&amp;nbsp;=&amp;nbsp;resp.json()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;res_data.get(&amp;quot;code&amp;quot;)&amp;nbsp;!=&amp;nbsp;200:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;接口返回异常：{res_data.get(&amp;#39;msg&amp;#39;)}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;轻量化字段提取，剔除冗余数据
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;goods_list&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;item&amp;nbsp;in&amp;nbsp;res_data[&amp;quot;data&amp;quot;][&amp;quot;list&amp;quot;]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;goods_list.append({
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;goods_id&amp;quot;:&amp;nbsp;item.get(&amp;quot;goods_id&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;item.get(&amp;quot;title&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;item.get(&amp;quot;price&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;min_order&amp;quot;:&amp;nbsp;item.get(&amp;quot;min_order&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;shop_name&amp;quot;:&amp;nbsp;item.get(&amp;quot;shop_name&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;total&amp;quot;:&amp;nbsp;res_data[&amp;quot;data&amp;quot;][&amp;quot;total&amp;quot;],&amp;nbsp;&amp;quot;goods&amp;quot;:&amp;nbsp;goods_list}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception&amp;nbsp;as&amp;nbsp;e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;请求异常：{e}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;time.sleep(2)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;None

if&amp;nbsp;__name__&amp;nbsp;==&amp;nbsp;&amp;quot;__main__&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;client&amp;nbsp;=&amp;nbsp;SouhaohuoSearch(&amp;quot;your_appkey&amp;quot;,&amp;nbsp;&amp;quot;your_appsecret&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;client.search_goods(keyword=&amp;quot;纯棉T恤&amp;quot;,&amp;nbsp;page=1)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;result:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;总商品数：{result[&amp;#39;total&amp;#39;]}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;g&amp;nbsp;in&amp;nbsp;result[&amp;quot;goods&amp;quot;]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(g)&lt;/pre&gt;&lt;/div&gt;&lt;p data-pid=&quot;VXrf3H0W&quot;&gt;代码逻辑解析&lt;/p&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;签名封装：按照平台规则对参数排序拼接生成 MD5 签名，这是接口鉴权核心。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;轻量化数据提取：只保留业务必需字段，过滤掉详情富文本、规格大图等冗余信息，减少内存占用。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;异常捕获：增加超时捕获，网络异常自动休眠，规避单次失败直接中断任务。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;p data-pid=&quot;vgbpONM8&quot;&gt;业务踩坑要点&lt;/p&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;分页漂移：搜好货接口在数据量大时，高页码会出现重复商品，业务层建议使用 goods_id 做内存去重。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;频次控制：单账号 QPS 建议控制在 2 以内，批量循环分页时，每页请求增加延时，防止触发接口限流。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;关键词编码：中文关键词会自动 url 编码，不要手动二次编码，否则会出现检索结果为空。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;权限边界：部分类目商品需要额外权限，无权限时接口不会直接报错，而是返回空列表，需要单独做判断。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Mon, 28 Sep 2026 15:40:31 +0800</pubDate></item></channel></rss>