<?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://www.apiproxylog.com/</link><description>Good Luck To You!</description><item><title>亚马逊SP-API关键词搜索接口：分页去重与风控适配实战方案</title><link>https://www.apiproxylog.com/?id=215</link><description>&lt;p&gt;&lt;span id=&quot;content&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;4yCTHWiL&quot;&gt;亚马逊商品关键词搜索接口（searchItems）是跨境选品、竞品数据分析、商品榜单监控的核心接口。市面上绝大多数教程仅实现基础鉴权和单次请求调用，完全忽略生产环境核心问题：接口分页数据漂移重复、高频请求触发风控拦截、不同站点搜索权重差异、无效广告数据混杂。本文跳出基础入门教学，主打&lt;strong&gt;数据净化+风控适配&lt;/strong&gt;，封装一套可直接上线、稳定容错的调用方案。&lt;br/&gt;该接口区别于普通电商接口，无传统page分页逻辑，依靠nextToken翻页，也是开发者批量采集数据时漏数据、重复数据的核心原因。本文针对性解决该行业通用痛点。&lt;/p&gt;&lt;p data-pid=&quot;EdpBhdHC&quot;&gt;&lt;br/&gt;一、核心对接难点分析&lt;br/&gt;1. 特殊分页机制：不支持页码遍历，仅支持令牌续翻，超时或高频请求会导致nextToken失效；2. 数据混杂问题：搜索结果自带推广广告商品，干扰真实榜单数据；3. 严格风控：短时间连续请求会直接返回429限流，无重试机制极易任务中断。&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/v2-24f6ad2b08e260906e14727058dd7d9d_1440w.jpg&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1158&quot; data-rawheight=&quot;689&quot; data-original-token=&quot;v2-f345aae57f2dde05db57cecfccec469e&quot; class=&quot;origin_image zh-lightbox-thumb&quot; width=&quot;1158&quot; data-original=&quot;https://pic2.zhimg.com/v2-24f6ad2b08e260906e14727058dd7d9d_r.jpg&quot;/&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p data-pid=&quot;IelniCUv&quot;&gt;&lt;a href=&quot;https://o0b.cn/iiiace&quot; target=&quot;_blank&quot;&gt;点击获取key和secret&lt;/a&gt;&lt;br/&gt;二、生产级完整封装代码&lt;br/&gt;&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;import&amp;nbsp;time
import&amp;nbsp;requests
import&amp;nbsp;hmac
import&amp;nbsp;hashlib
from&amp;nbsp;datetime&amp;nbsp;import&amp;nbsp;datetime

class&amp;nbsp;AmazonSearchApi:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;access_key,&amp;nbsp;secret_key,&amp;nbsp;region=&amp;quot;us&amp;quot;):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.access_key&amp;nbsp;=&amp;nbsp;access_key
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.secret_key&amp;nbsp;=&amp;nbsp;secret_key
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.host&amp;nbsp;=&amp;nbsp;{
&amp;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;us&amp;quot;:&amp;nbsp;&amp;quot;sellingpartnerapi-na.amazon.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;quot;eu&amp;quot;:&amp;nbsp;&amp;quot;sellingpartnerapi-eu.amazon.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;quot;jp&amp;quot;:&amp;nbsp;&amp;quot;sellingpartnerapi-fe.amazon.com&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}[region]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.url&amp;nbsp;=&amp;nbsp;f&amp;quot;https://{self.host}/products/2020-09-01/search&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.item_set&amp;nbsp;=&amp;nbsp;set()&amp;nbsp;#&amp;nbsp;全局去重

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;生成AWS4实时签名
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;build_sign(self,&amp;nbsp;params,&amp;nbsp;date_stamp,&amp;nbsp;amz_date):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;canonical_query&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;amp;&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(params.items())])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;canonical&amp;nbsp;=&amp;nbsp;f&amp;quot;GET\n/products/2020-09-01/search\n{canonical_query}\nhost:{self.host}\nx-amz-date:{amz_date}\n\nhost;x-amz-date\n{hashlib.sha256(b&amp;#39;&amp;#39;).hexdigest()}&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;k_secret&amp;nbsp;=&amp;nbsp;f&amp;quot;AWS4{self.secret_key}&amp;quot;.encode()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;k_date&amp;nbsp;=&amp;nbsp;hmac.new(k_secret,&amp;nbsp;date_stamp.encode(),&amp;nbsp;hashlib.sha256).digest()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;k_region&amp;nbsp;=&amp;nbsp;hmac.new(k_date,&amp;nbsp;b&amp;quot;us-east-1&amp;quot;,&amp;nbsp;hashlib.sha256).digest()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;k_service&amp;nbsp;=&amp;nbsp;hmac.new(k_region,&amp;nbsp;b&amp;quot;sellingpartnerapi&amp;quot;,&amp;nbsp;hashlib.sha256).digest()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;k_sign&amp;nbsp;=&amp;nbsp;hmac.new(k_service,&amp;nbsp;b&amp;quot;aws4_request&amp;quot;,&amp;nbsp;hashlib.sha256).digest()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;hmac.new(k_sign,&amp;nbsp;canonical.encode(),&amp;nbsp;hashlib.sha256).hexdigest()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;关键词搜索+去重+过滤广告
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;search_keyword(self,&amp;nbsp;keyword,&amp;nbsp;max_page=3):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;res_list&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;next_token&amp;nbsp;=&amp;nbsp;None
&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(max_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;time.sleep(1.5)&amp;nbsp;#&amp;nbsp;风控限流适配
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;date&amp;nbsp;=&amp;nbsp;datetime.utcnow()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;date_stamp&amp;nbsp;=&amp;nbsp;date.strftime(&amp;quot;%Y%m%d&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;amz_date&amp;nbsp;=&amp;nbsp;date.strftime(&amp;quot;%Y%m%dT%H%M%SZ&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;params&amp;nbsp;=&amp;nbsp;{&amp;quot;keywords&amp;quot;:&amp;nbsp;keyword,&amp;nbsp;&amp;quot;searchContext&amp;quot;:&amp;nbsp;&amp;quot;All&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;next_token:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;nextToken&amp;quot;]&amp;nbsp;=&amp;nbsp;next_token
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;Host&amp;quot;:&amp;nbsp;self.host,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;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;X-Amz-Date&amp;quot;:&amp;nbsp;amz_date,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;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;AWS4-HMAC-SHA256&amp;nbsp;Credential={self.access_key}/{date_stamp}/us-east-1/sellingpartnerapi/aws4_request,&amp;nbsp;Signature={self.build_sign(params,date_stamp,amz_date)}&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;resp&amp;nbsp;=&amp;nbsp;requests.get(self.url,&amp;nbsp;headers=headers,&amp;nbsp;params=params,&amp;nbsp;timeout=15)
&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;if&amp;nbsp;&amp;quot;errors&amp;quot;&amp;nbsp;in&amp;nbsp;data:break
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;items&amp;nbsp;=&amp;nbsp;data.get(&amp;quot;SearchResult&amp;quot;,{}).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;for&amp;nbsp;item&amp;nbsp;in&amp;nbsp;items:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;asin&amp;nbsp;=&amp;nbsp;item.get(&amp;quot;ASIN&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;if&amp;nbsp;not&amp;nbsp;asin&amp;nbsp;or&amp;nbsp;asin&amp;nbsp;in&amp;nbsp;self.item_set&amp;nbsp;or&amp;nbsp;item.get(&amp;quot;IsAdvertisement&amp;quot;,False):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;self.item_set.add(asin)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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_list.append({&amp;quot;asin&amp;quot;:asin,&amp;quot;title&amp;quot;:item.get(&amp;quot;Title&amp;quot;),&amp;quot;brand&amp;quot;:item.get(&amp;quot;Brand&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;next_token&amp;nbsp;=&amp;nbsp;data.get(&amp;quot;SearchResult&amp;quot;,{}).get(&amp;quot;NextToken&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;not&amp;nbsp;next_token:break
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;res_list

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;AmazonSearchApi(&amp;quot;ACCESS_KEY&amp;quot;,&amp;quot;SECRET_KEY&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(api.search_keyword(&amp;quot;wireless&amp;nbsp;earbuds&amp;quot;,2))&lt;/pre&gt;&lt;/div&gt;&lt;p data-pid=&quot;BJSf6N6a&quot;&gt;&lt;br/&gt;三、核心优化亮点&lt;br/&gt;&lt;strong&gt;1. 令牌分页兼容&lt;/strong&gt;：适配亚马逊专属nextToken翻页机制，解决传统分页逻辑失效问题，完整抓取多页数据。&lt;br/&gt;&lt;strong&gt;2. 双层数据净化&lt;/strong&gt;：通过ASIN全局去重，同时过滤广告推广商品，保证搜索数据为自然排名真实数据。&lt;br/&gt;&lt;strong&gt;3. 限流主动适配&lt;/strong&gt;：内置固定请求间隔，主动规避429限流报错，无需复杂重试逻辑即可稳定运行。&lt;/p&gt;&lt;p data-pid=&quot;RsfnnPRp&quot;&gt;&lt;br/&gt;四、落地总结&lt;br/&gt;亚马逊关键词搜索接口最大难点不在于签名鉴权，而是不规则分页、数据混杂和平台风控。本文摒弃简单请求演示，聚焦数据准确性与接口稳定性，适配选品分析、竞品监控、榜单采集等生产场景，是区别于通用教程的核心优势。&lt;/p&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Wed, 12 Aug 2026 17:39:41 +0800</pubDate></item><item><title>亚马逊商品详情接口：多站点适配与时效异常优化实战</title><link>https://www.apiproxylog.com/?id=214</link><description>&lt;p&gt;&lt;span id=&quot;content&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;is_901vR&quot;&gt;亚马逊SP-API商品详情接口是跨境商品数据分析、店铺铺货、竞品监控的核心能力。目前多数开发教程仅实现基础签名调用，忽略亚马逊独有特性：接口签名秒级时效、全球多站点域名隔离、商品变体数据嵌套混乱、下架商品返回空结构体等生产级问题。本文摒弃入门式教学，聚焦&lt;strong&gt;接口稳定性优化、多站点兼容、脏数据清洗&lt;/strong&gt;，提供可直接上线的封装方案。&lt;br/&gt;本次对接基于亚马逊最新SP-API规范，采用AWS签名4.0机制，适配北美、欧洲、东南亚全站点，解决常规调用中随机报错、数据缺失、程序中断等高频问题。&lt;/p&gt;&lt;p data-pid=&quot;6aL03uR2&quot;&gt;&lt;br/&gt;一、核心对接痛点梳理&lt;br/&gt;区别于国内电商接口，亚马逊接口核心难点集中三点：一是签名仅有效期15秒，超时直接鉴权失败；二是不同站点商品ASIN通用，但接口域名独立，跨域调用直接404；三是变体商品层级复杂，原始数据嵌套混乱，无统一解析规则。&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-3b2ce10cfdc9bf9a8c5f588d3fc71c88_720w.jpg&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1175&quot; data-rawheight=&quot;608&quot; data-original-token=&quot;v2-a40568a5765f5e8dc1f3711ae13793a8&quot; class=&quot;origin_image zh-lightbox-thumb lazy&quot; width=&quot;1175&quot; data-original=&quot;https://pic1.zhimg.com/v2-3b2ce10cfdc9bf9a8c5f588d3fc71c88_r.jpg&quot; data-actualsrc=&quot;https://pic1.zhimg.com/v2-3b2ce10cfdc9bf9a8c5f588d3fc71c88_1440w.jpg&quot; height=&quot;608&quot; data-lazy-status=&quot;ok&quot;/&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p data-pid=&quot;_kbn3rSR&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;hORoXE_s&quot;&gt;二、优化版完整调用代码&lt;br/&gt;基于Python封装，整合实时签名、站点适配、异常捕获、数据归一化，解决时效和兼容问题：&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
import&amp;nbsp;hmac
from&amp;nbsp;datetime&amp;nbsp;import&amp;nbsp;datetime

class&amp;nbsp;AmazonItemDetail:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;access_key,&amp;nbsp;secret_key,&amp;nbsp;region=&amp;quot;us&amp;quot;):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.access_key&amp;nbsp;=&amp;nbsp;access_key
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.secret_key&amp;nbsp;=&amp;nbsp;secret_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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.host_map&amp;nbsp;=&amp;nbsp;{&amp;quot;us&amp;quot;:&amp;quot;sellingpartnerapi-na.amazon.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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;eu&amp;quot;:&amp;quot;sellingpartnerapi-eu.amazon.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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;jp&amp;quot;:&amp;quot;sellingpartnerapi-fe.amazon.com&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.host&amp;nbsp;=&amp;nbsp;self.host_map.get(region,&amp;nbsp;self.host_map[&amp;quot;us&amp;quot;])

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;实时时效签名（解决签名过期问题）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_aws_sign(self,&amp;nbsp;canonical_request,&amp;nbsp;date_stamp):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;k_secret&amp;nbsp;=&amp;nbsp;f&amp;quot;AWS4{self.secret_key}&amp;quot;.encode()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;k_date&amp;nbsp;=&amp;nbsp;hmac.new(k_secret,&amp;nbsp;date_stamp.encode(),&amp;nbsp;hashlib.sha256).digest()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;k_region&amp;nbsp;=&amp;nbsp;hmac.new(k_date,&amp;nbsp;b&amp;quot;us-east-1&amp;quot;,&amp;nbsp;hashlib.sha256).digest()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;k_service&amp;nbsp;=&amp;nbsp;hmac.new(k_region,&amp;nbsp;b&amp;quot;sellingpartnerapi&amp;quot;,&amp;nbsp;hashlib.sha256).digest()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;k_signing&amp;nbsp;=&amp;nbsp;hmac.new(k_service,&amp;nbsp;b&amp;quot;aws4_request&amp;quot;,&amp;nbsp;hashlib.sha256).digest()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;hmac.new(k_signing,&amp;nbsp;canonical_request.encode(),&amp;nbsp;hashlib.sha256).hexdigest()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;商品详情查询+数据归一化
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_product_detail(self,&amp;nbsp;asin):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;date_now&amp;nbsp;=&amp;nbsp;datetime.utcnow()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;date_stamp&amp;nbsp;=&amp;nbsp;date_now.strftime(&amp;quot;%Y%m%d&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;amz_date&amp;nbsp;=&amp;nbsp;date_now.strftime(&amp;quot;%Y%m%dT%H%M%SZ&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;url&amp;nbsp;=&amp;nbsp;f&amp;quot;https://{self.host}/products/2020-09-01/products/{asin}&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;headers&amp;nbsp;=&amp;nbsp;{&amp;quot;Host&amp;quot;:self.host,&amp;nbsp;&amp;quot;X-Amz-Date&amp;quot;:amz_date}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;canonical&amp;nbsp;=&amp;nbsp;f&amp;quot;GET\n/products/2020-09-01/products/{asin}\n\nhost:{self.host}\nx-amz-date:{amz_date}\n\nhost;x-amz-date\n{hashlib.sha256(b&amp;#39;&amp;#39;).hexdigest()}&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;headers[&amp;quot;Authorization&amp;quot;]&amp;nbsp;=&amp;nbsp;f&amp;quot;AWS4-HMAC-SHA256&amp;nbsp;Credential={self.access_key}/{date_stamp}/us-east-1/sellingpartnerapi/aws4_request,&amp;nbsp;Signature={self.get_aws_sign(canonical,date_stamp)}&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;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;res&amp;nbsp;=&amp;nbsp;requests.get(url,&amp;nbsp;headers=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;data&amp;nbsp;=&amp;nbsp;res.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;&amp;quot;errors&amp;quot;&amp;nbsp;in&amp;nbsp;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;return&amp;nbsp;{&amp;quot;status&amp;quot;:0,&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self.parse_data(data)
&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;status&amp;quot;:0,&amp;nbsp;&amp;quot;msg&amp;quot;:str(e),&amp;nbsp;&amp;quot;data&amp;quot;:{}}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;标准化清洗数据
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;parse_data(self,&amp;nbsp;raw):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;product&amp;nbsp;=&amp;nbsp;raw.get(&amp;quot;ProductInfo&amp;quot;,&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;quot;asin&amp;quot;:product.get(&amp;quot;Identifiers&amp;quot;,{}).get(&amp;quot;MarketplaceASIN&amp;quot;,{}).get(&amp;quot;ASIN&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;title&amp;quot;:product.get(&amp;quot;Title&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;brand&amp;quot;:product.get(&amp;quot;Brand&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;category&amp;quot;:product.get(&amp;quot;ProductGroup&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;is_valid&amp;quot;:bool(product)
&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;AmazonItemDetail(&amp;quot;你的ACCESS_KEY&amp;quot;,&amp;quot;你的SECRET_KEY&amp;quot;,&amp;quot;us&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(client.get_product_detail(&amp;quot;B0XXXXXXXXX&amp;quot;))&lt;/pre&gt;&lt;/div&gt;&lt;p data-pid=&quot;vxoBKwo0&quot;&gt;&lt;br/&gt;三、差异化优化亮点&lt;br/&gt;&lt;strong&gt;1. 动态时效签名&lt;/strong&gt;：摒弃固定签名方式，每次请求生成实时签名，彻底解决亚马逊15秒签名过期报错，适配高频调用场景。&lt;br/&gt;&lt;strong&gt;2. 多站点一键适配&lt;/strong&gt;：内置主流站点域名映射，无需手动修改接口地址，一套代码适配全球站点商品查询。&lt;br/&gt;&lt;strong&gt;3. 结构化数据清洗&lt;/strong&gt;：屏蔽原始接口复杂嵌套结构，统一输出简洁字段，自动识别下架、无效商品，避免空数据导致程序报错。&lt;br/&gt;四、线上落地注意事项&lt;br/&gt;亚马逊SP-API有严格QPS限制，单账号每秒请求不超过2次，批量查询需增设间隔；同时需定期刷新授权令牌，令牌失效会导致接口权限拦截。禁止高频批量请求，否则会触发平台风控，限制接口调用权限。&lt;br/&gt;本文方案从稳定性、兼容性角度优化，规避了通用Demo的各类隐性问题，完全适配跨境业务常态化商品数据同步、竞品监控等生产场景。&lt;/p&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Tue, 11 Aug 2026 17:53:27 +0800</pubDate></item><item><title>速卖通商品详情接口实战：多站点字段兼容与脏数据过滤方案</title><link>https://www.apiproxylog.com/?id=213</link><description>&lt;p&gt;&lt;span id=&quot;content&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;RZ87IJEE&quot;&gt;前言&lt;/p&gt;&lt;p data-pid=&quot;d9ULqlyp&quot;&gt;大部分公开教程只演示简单调用获取商品基础信息，很少处理跨境平台真实痛点：不同站点返回字段差异、多语言字段乱码、规格
 SKU 
数组嵌套层级不稳定、接口返回空片段。本文不从简单请求示例切入，聚焦业务落地，增加字段归一化、脏数据拦截逻辑，适合爬虫业务、商品同步系统直接参考。&lt;/p&gt;&lt;p data-pid=&quot;sruFDGYG&quot;&gt;前置说明&lt;/p&gt;&lt;p data-pid=&quot;6G35I-zU&quot;&gt;速卖通开放平台商品详情接口，不同国家站点返回结构会发生变动，同一接口 US、RU、ES 站点 SKU、图片、物流字段 key 不完全一致。直接按固定 key 取值，生产环境极易出现 KeyError，导致程序中断。&lt;br/&gt; 开发前需要准备：应用 AppKey、AppSecret、商品 ID，接口权限已开通，注意接口 QPS 限流，高频调用需要增加休眠与重试。&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-0e1eacb71d61d3cf916b754ec977b79c_720w.webp&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1164&quot; data-rawheight=&quot;596&quot; data-original-token=&quot;v2-10e1235c5deaf4d006c1cffe31751ec6&quot; class=&quot;origin_image zh-lightbox-thumb lazy&quot; width=&quot;1164&quot; data-original=&quot;https://pica.zhimg.com/v2-0e1eacb71d61d3cf916b754ec977b79c_r.jpg&quot; data-actualsrc=&quot;https://pica.zhimg.com/v2-0e1eacb71d61d3cf916b754ec977b79c_1440w.jpg&quot; height=&quot;596&quot; data-lazy-status=&quot;ok&quot;/&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p data-pid=&quot;EQGszgo1&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;ZIMsjq0D&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;AliExpressDetailClient:
&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.url&amp;nbsp;=&amp;nbsp;&amp;quot;https://gw.api.aliexpress.com/openapi&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;normalize_field(self,&amp;nbsp;raw_data):
&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;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;&amp;nbsp;&amp;nbsp;&amp;quot;item_id&amp;quot;:&amp;nbsp;raw_data.get(&amp;quot;item_id&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;quot;title&amp;quot;:&amp;nbsp;raw_data.get(&amp;quot;subject&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;quot;price&amp;quot;:&amp;nbsp;raw_data.get(&amp;quot;price&amp;quot;,&amp;nbsp;&amp;quot;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;main_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;nbsp;&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;&amp;nbsp;&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;img_raw&amp;nbsp;=&amp;nbsp;raw_data.get(&amp;quot;main_image_urls&amp;quot;,&amp;nbsp;[])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;res[&amp;quot;main_images&amp;quot;]&amp;nbsp;=&amp;nbsp;[i&amp;nbsp;for&amp;nbsp;i&amp;nbsp;in&amp;nbsp;img_raw&amp;nbsp;if&amp;nbsp;i&amp;nbsp;and&amp;nbsp;isinstance(i,&amp;nbsp;str)]
&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;sku_raw&amp;nbsp;=&amp;nbsp;raw_data.get(&amp;quot;sku_info_list&amp;quot;)&amp;nbsp;or&amp;nbsp;raw_data.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;for&amp;nbsp;sku&amp;nbsp;in&amp;nbsp;sku_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;if&amp;nbsp;not&amp;nbsp;isinstance(sku,&amp;nbsp;dict):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;sku_item&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;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;sku_id&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;sale_price&amp;quot;:&amp;nbsp;sku.get(&amp;quot;sku_price&amp;quot;,&amp;quot;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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;stock_num&amp;quot;:&amp;nbsp;int(sku.get(&amp;quot;stock&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;res[&amp;quot;sku_list&amp;quot;].append(sku_item)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;res[&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;res[&amp;quot;stock&amp;quot;]&amp;nbsp;=&amp;nbsp;sum(s[&amp;quot;stock_num&amp;quot;]&amp;nbsp;for&amp;nbsp;s&amp;nbsp;in&amp;nbsp;res[&amp;quot;sku_list&amp;quot;])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;res

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_item_detail(self,&amp;nbsp;item_id,&amp;nbsp;session=None):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;session&amp;nbsp;=&amp;nbsp;session&amp;nbsp;or&amp;nbsp;requests.Session()
&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;timestamp&amp;quot;:&amp;nbsp;int(time.time()*1000),
&amp;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;method&amp;quot;:&amp;quot;aliexpress.item.get&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;item_id&amp;quot;:&amp;nbsp;item_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;resp&amp;nbsp;=&amp;nbsp;session.get(self.url,&amp;nbsp;params=params,&amp;nbsp;timeout=12)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;json_data&amp;nbsp;=&amp;nbsp;resp.json()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;json_data.get(&amp;quot;error_response&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;success&amp;quot;:False,&amp;quot;msg&amp;quot;:json_data[&amp;quot;error_response&amp;quot;]}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw&amp;nbsp;=&amp;nbsp;json_data.get(&amp;quot;response&amp;quot;,{})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;success&amp;quot;:True,&amp;quot;data&amp;quot;:self.normalize_field(raw)}

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;AliExpressDetailClient(&amp;quot;your_appkey&amp;quot;,&amp;quot;your_appsecret&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ret&amp;nbsp;=&amp;nbsp;client.get_item_detail(&amp;quot;1234567890&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(ret)&lt;/pre&gt;&lt;/div&gt;&lt;p data-pid=&quot;Xoudc2U1&quot;&gt;代码核心逻辑解读&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;封装&lt;code&gt;normalize_field&lt;/code&gt;归一化函数，这是本文重点，不直接读取原始返回，统一输出固定格式字典，屏蔽不同站点字段差异。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;SKU 做类型判断，接口偶尔返回&lt;code&gt;None&lt;/code&gt;或者非数组对象，直接遍历会直接抛异常，增加类型过滤。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;自动聚合全部 SKU 库存，业务系统不需要重复循环计算。&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;FIf0dWgK&quot;&gt;踩坑总结&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&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;li&gt;&lt;p&gt;多语言：标题、描述字段会随调用站点语言切换，不要硬编码字段名。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;图片地址：部分图片链接会携带过期 token，存储时注意识别，否则一段时间后图片失效。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Mon, 10 Aug 2026 16:47:35 +0800</pubDate></item><item><title>速卖通关键词商品列表接口：业务层容错与分页偏移实战方案</title><link>https://www.apiproxylog.com/?id=212</link><description>&lt;p&gt;&lt;span id=&quot;content&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;ctC3DmLh&quot;&gt;前言&lt;/p&gt;&lt;p data-pid=&quot;ZdFXNCUi&quot;&gt;多数网上教程只演示简单调用速卖通关键词搜索接口，直接拿返回结果做业务输出。但实际对接中经常遇到：页码递增但数据重复、部分类目返回字段缺失、接口限流随机报错、多语言站点参数适配混乱等问题。本文不从基础鉴权讲起，聚焦&lt;strong&gt;业务层封装、偏移校验、脏数据过滤&lt;/strong&gt;，给出可直接用于小规模采集业务的 Python 实现，解决线上容易踩的隐性问题。&lt;/p&gt;&lt;p data-pid=&quot;-UtU7JIB&quot;&gt;前置说明&lt;/p&gt;&lt;p data-pid=&quot;5daU9PY9&quot;&gt;调用速卖通开放平台搜索接口，需要开发者
 AppKey、AppSecret，获取 access_token。接口支持关键词、类目、排序、分页参数。注意官方接口并非 pageNum 
简单累加，部分场景会出现数据漂移，单纯循环 page 会出现重复商品或者漏数据。&lt;/p&gt;&lt;p data-pid=&quot;oPBpaWdD&quot;&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://pic3.zhimg.com/80/v2-5a0d6a5cf4cb609f2f38b90dbd90f8de_720w.jpg&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1163&quot; data-rawheight=&quot;708&quot; data-original-token=&quot;v2-eb2467a9c86b72aa5c358abf1994fae3&quot; class=&quot;origin_image zh-lightbox-thumb lazy&quot; width=&quot;1163&quot; data-original=&quot;https://pic3.zhimg.com/v2-5a0d6a5cf4cb609f2f38b90dbd90f8de_r.jpg&quot; data-actualsrc=&quot;https://pic3.zhimg.com/v2-5a0d6a5cf4cb609f2f38b90dbd90f8de_1440w.jpg&quot; height=&quot;708&quot; data-lazy-status=&quot;ok&quot;/&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p data-pid=&quot;rNpiSTCw&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;zBR6xIzl&quot;&gt;核心代码示例&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;import&amp;nbsp;time
import&amp;nbsp;requests

class&amp;nbsp;AliExpressSearchClient:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;app_key,&amp;nbsp;access_token):
&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.access_token&amp;nbsp;=&amp;nbsp;access_token
&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://gw.api.aliexpress.com/openapi&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.seen_item_ids&amp;nbsp;=&amp;nbsp;set()&amp;nbsp;&amp;nbsp;#&amp;nbsp;本地去重集合

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;search_by_keyword(self,&amp;nbsp;keyword,&amp;nbsp;page=1,&amp;nbsp;page_size=20,&amp;nbsp;sort=&amp;quot;sale&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;timestamp&amp;quot;:&amp;nbsp;str(int(time.time()*1000)),
&amp;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;access_token&amp;quot;:&amp;nbsp;self.access_token,
&amp;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;method&amp;quot;:&amp;nbsp;&amp;quot;aliexpress.affiliate.product.query&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;sign_method&amp;quot;:&amp;nbsp;&amp;quot;md5&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;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_no&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;sort&amp;quot;:&amp;nbsp;sort
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;requests.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;result&amp;nbsp;=&amp;nbsp;resp.json()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;result

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_clean_goods_list(self,&amp;nbsp;keyword,&amp;nbsp;max_page=3):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;clean_list&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;page&amp;nbsp;in&amp;nbsp;range(1,&amp;nbsp;max_page&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;time.sleep(1.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;raw_data&amp;nbsp;=&amp;nbsp;self.search_by_keyword(keyword,&amp;nbsp;page=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;resp_body&amp;nbsp;=&amp;nbsp;raw_data.get(&amp;quot;aliexpress_affiliate_product_query_response&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;product_list&amp;nbsp;=&amp;nbsp;resp_body.get(&amp;quot;result&amp;quot;,&amp;nbsp;{}).get(&amp;quot;products&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;if&amp;nbsp;not&amp;nbsp;product_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;break
&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;product_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;item_id&amp;nbsp;=&amp;nbsp;item.get(&amp;quot;product_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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;item_id&amp;nbsp;or&amp;nbsp;item_id&amp;nbsp;in&amp;nbsp;self.seen_item_ids:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;self.seen_item_ids.add(item_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;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;product_id&amp;quot;:&amp;nbsp;item_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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;item.get(&amp;quot;product_title&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;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;original_price&amp;quot;:&amp;nbsp;item.get(&amp;quot;original_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;sales&amp;quot;:&amp;nbsp;item.get(&amp;quot;sales&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_img&amp;quot;:&amp;nbsp;item.get(&amp;quot;product_main_image_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;clean_list.append(goods)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;clean_list

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;AliExpressSearchClient(app_key=&amp;quot;your_appkey&amp;quot;,&amp;nbsp;access_token=&amp;quot;your_token&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;data&amp;nbsp;=&amp;nbsp;client.get_clean_goods_list(keyword=&amp;quot;wireless&amp;nbsp;mouse&amp;quot;,&amp;nbsp;max_page=2)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;有效商品数量：{len(data)}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;g&amp;nbsp;in&amp;nbsp;data[:5]:
&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;Y3dUj-xX&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;seen_item_ids 集合做本地去重&lt;/strong&gt;：速卖通搜索接口分页存在数据偏移，翻页会返回重复商品，不能完全依赖接口分页，内存集合做 ID 过滤，保证业务数据唯一性。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;强制休眠间隔&lt;/strong&gt;：官方 QPS 有限制，高频调用会返回权限异常，固定间隔可以降低报错概率。&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;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;p data-pid=&quot;hi9Opprc&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;分页上限：接口并非可以无限翻页，一般搜索结果有效页数有限，不要设置过大 max_page。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Token 过期：access_token 存在有效期，生产环境要增加 token 自动刷新逻辑。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Fri, 07 Aug 2026 17:18:22 +0800</pubDate></item><item><title>美客多商品详情接口：多区域兼容与字段归一化实战</title><link>https://www.apiproxylog.com/?id=211</link><description>&lt;p&gt;&lt;span id=&quot;content&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;UbtL1CC7&quot;&gt;前言&lt;/p&gt;&lt;p data-pid=&quot;Rc4TSJyf&quot;&gt;大部分教程只演示简单调用获取商品基础信息，很少关注拉美多站点差异、多语言属性、附属描述接口分离、token
 过期重试这些生产环境痛点。美客多不同国家站点（墨西哥 MLM、阿根廷 MLA、巴西 
MLB）返回的字段存在细微差异，直接解析极易出现键不存在报错。本文从业务集成角度，实现具备异常捕获、字段兼容、描述接口联动的调用封装，适合用于商品监控、数据同步场景。&lt;/p&gt;&lt;p data-pid=&quot;m4_HPUJo&quot;&gt;接口基础说明&lt;/p&gt;&lt;p data-pid=&quot;olxhVDJo&quot;&gt;商品详情核心接口 &lt;code&gt;GET /items/{item_id}&lt;/code&gt;，基于 OAuth2.0 鉴权，必须携带 Bearer 令牌。注意商品 ID 前缀代表站点，MLM 为墨西哥、MLA 阿根廷、MLB 巴西，ID 与站点不匹配直接返回 404。商品长描述不在主接口返回，需要额外调用 &lt;code&gt;/items/{item_id}/description&lt;/code&gt; 单独获取，这是很多开发者容易遗漏的点MercadoLib...。&lt;/p&gt;&lt;p data-pid=&quot;AVHywDfC&quot;&gt;&lt;strong&gt;常见状态码&lt;/strong&gt;&lt;/p&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;200：正常返回&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;401：token 失效，需要刷新令牌&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;404：商品下架、ID 错误、站点不匹配&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;429：触发接口限流，需降低请求频率&lt;/p&gt;&lt;/li&gt;&lt;/ul&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-b587f98547acb6904c5df59e0b778892_720w.jpg&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1161&quot; data-rawheight=&quot;582&quot; data-original-token=&quot;v2-d2aeb367ca9572cca16c4fc118c5b154&quot; class=&quot;origin_image zh-lightbox-thumb lazy&quot; width=&quot;1161&quot; data-original=&quot;https://pica.zhimg.com/v2-b587f98547acb6904c5df59e0b778892_r.jpg&quot; data-actualsrc=&quot;https://pica.zhimg.com/v2-b587f98547acb6904c5df59e0b778892_1440w.jpg&quot; height=&quot;582&quot; data-lazy-status=&quot;ok&quot;/&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p data-pid=&quot;IyUmWSIs&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;UtMr04gq&quot;&gt;Python 核心封装代码&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;MeliItemClient:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;access_token):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.token&amp;nbsp;=&amp;nbsp;access_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.mercadolibre.com&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.headers&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;def&amp;nbsp;get_item_detail(self,&amp;nbsp;item_id):
&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;url&amp;nbsp;=&amp;nbsp;f&amp;quot;{self.base_url}/items/{item_id}&amp;quot;
&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;requests.get(url,&amp;nbsp;headers=self.headers,&amp;nbsp;timeout=20)
&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;401:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;error&amp;quot;:&amp;nbsp;&amp;quot;token_invalid&amp;quot;,&amp;nbsp;&amp;quot;msg&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;if&amp;nbsp;resp.status_code&amp;nbsp;==&amp;nbsp;404:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;error&amp;quot;:&amp;nbsp;&amp;quot;item_not_found&amp;quot;,&amp;nbsp;&amp;quot;msg&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;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;return&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;error&amp;quot;:&amp;quot;request_fail&amp;quot;,&amp;nbsp;&amp;quot;msg&amp;quot;:str(e)}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_item_desc(self,&amp;nbsp;item_id):
&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;url&amp;nbsp;=&amp;nbsp;f&amp;quot;{self.base_url}/items/{item_id}/description&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resp&amp;nbsp;=&amp;nbsp;requests.get(url,&amp;nbsp;headers=self.headers,&amp;nbsp;timeout=20)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;resp.status_code&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;resp.json().get(&amp;quot;plain_text&amp;quot;,&amp;quot;&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;parse_normalize(self,&amp;nbsp;raw_data):
&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;if&amp;nbsp;&amp;quot;error&amp;quot;&amp;nbsp;in&amp;nbsp;raw_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;return&amp;nbsp;raw_data
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;&amp;nbsp;&amp;nbsp;&amp;quot;item_id&amp;quot;:&amp;nbsp;raw_data.get(&amp;quot;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;:&amp;nbsp;raw_data.get(&amp;quot;title&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;price&amp;quot;:&amp;nbsp;raw_data.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;quot;currency&amp;quot;:&amp;nbsp;raw_data.get(&amp;quot;currency_id&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;stock&amp;quot;:&amp;nbsp;raw_data.get(&amp;quot;available_quantity&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;condition&amp;quot;:&amp;nbsp;raw_data.get(&amp;quot;condition&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;site_id&amp;quot;:&amp;nbsp;raw_data.get(&amp;quot;site_id&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;seller_id&amp;quot;:&amp;nbsp;raw_data.get(&amp;quot;seller&amp;quot;,{}).get(&amp;quot;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;pic_list&amp;quot;:&amp;nbsp;[p.get(&amp;quot;url&amp;quot;)&amp;nbsp;for&amp;nbsp;p&amp;nbsp;in&amp;nbsp;raw_data.get(&amp;quot;pictures&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;attributes&amp;quot;:&amp;nbsp;raw_data.get(&amp;quot;attributes&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;res

if&amp;nbsp;__name__&amp;nbsp;==&amp;nbsp;&amp;quot;__main__&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;token&amp;nbsp;=&amp;nbsp;&amp;quot;your_access_token&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;client&amp;nbsp;=&amp;nbsp;MeliItemClient(token)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;item&amp;nbsp;=&amp;nbsp;client.get_item_detail(&amp;quot;MLM123456789&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;detail&amp;nbsp;=&amp;nbsp;client.parse_normalize(item)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;desc_text&amp;nbsp;=&amp;nbsp;client.get_item_desc(&amp;quot;MLM123456789&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;detail[&amp;quot;description&amp;quot;]&amp;nbsp;=&amp;nbsp;desc_text
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(detail)&lt;/pre&gt;&lt;/div&gt;&lt;p data-pid=&quot;_iD8XQWQ&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;code&gt;parse_normalize&lt;/code&gt;归一化函数，全部使用&lt;code&gt;.get()&lt;/code&gt;取值，防止某站点缺失字段直接抛出 KeyError 导致程序中断。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;对 401、404 业务状态单独拦截，方便上层业务做重试、跳过下架商品逻辑。&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;MZW0E8z3&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;货币单位陷阱&lt;/strong&gt;：墨西哥货币 MXN 符号同样是&lt;code&gt;$&lt;/code&gt;，不能只看符号，必须保存&lt;code&gt;currency_id&lt;/code&gt;字段区分币种，否则价格统计错乱。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;限流策略&lt;/strong&gt;：授权后接口峰值约 2 万次每小时，批量拉取建议加入延时，大量请求务必做好 429 捕获和退避。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;跨站点查询&lt;/strong&gt;：不要拿 MLM 的商品 ID 去请求 MLA 站点接口，一定会返回 404，ID 自带站点前缀，调用前校验前缀。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;属性字段异构&lt;/strong&gt;：不同类目&lt;code&gt;attributes&lt;/code&gt;内部 key 不统一，不能硬编码下标读取，需要循环匹配 name 取值。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Thu, 06 Aug 2026 17:43:00 +0800</pubDate></item><item><title>转转商品详情接口实战：二手商品多状态字段解析与价格归一化处理 (Python)</title><link>https://www.apiproxylog.com/?id=210</link><description>&lt;p&gt;&lt;span id=&quot;content&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;7geqvRam&quot;&gt;前言&lt;/p&gt;&lt;p data-pid=&quot;SR07xmLW&quot;&gt;转转作为主流二手交易平台，商品数据和全新电商平台存在明显区别。网上多数示例仅提取标题、标价，忽略二手场景关键信息：商品成色、验机报告标识、是否支持平台质保、个人卖家与商家区分、实际到手价等业务字段。在做二手比价、商品监控业务时，如果直接拿原始返回字段，很容易出现价格错乱、成色识别错误、无法区分验机机器等问题。&lt;/p&gt;&lt;p data-pid=&quot;wbcCiOL7&quot;&gt;本文不从简单请求调用入手，重点聚焦二手业务层的&lt;a class=&quot;RichContent-EntityWord css-b7erz1&quot; data-za-not-track-link=&quot;true&quot; data-paste-text=&quot;true&quot; href=&quot;https://zhida.zhihu.com/search?content_id=280655384&amp;content_type=Article&amp;match_order=1&amp;q=%E6%95%B0%E6%8D%AE%E6%B8%85%E6%B4%97&amp;zhida_source=entity&quot; target=&quot;_blank&quot;&gt;数据清洗&lt;svg width=&quot;10px&quot; height=&quot;10px&quot; viewbox=&quot;0 0 16 16&quot; class=&quot;ZDI ZDI--FourPointedStar16 css-1dvsrp&quot; fill=&quot;currentColor&quot;&gt;&lt;/svg&gt;&lt;/a&gt;、状态映射、异常兜底逻辑，封装可直接用于业务系统的工具函数，同时增加分级异常捕获，避免接口波动导致整个程序中断。&lt;/p&gt;&lt;p data-pid=&quot;LQUwfGdg&quot;&gt;前置准备&lt;/p&gt;&lt;p data-pid=&quot;0CMFa7_L&quot;&gt;对接开放接口需要提前申请应用凭证，获取 app_key、app_secret。接口返回为 JSON 格式，二手商品会存在部分字段为空的情况，例如未走验机服务则验机相关字段全部为空，代码必须做好空值兼容。&lt;br/&gt; 依赖库仅需要 requests，执行安装：&lt;code&gt;pip install requests&lt;/code&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://pic1.zhimg.com/v2-3067129d92a7ba156ed55bd9c70abe16_1440w.jpg&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1177&quot; data-rawheight=&quot;580&quot; data-original-token=&quot;v2-0c7a8c8dccd7f5234d8baac0db4c80f2&quot; class=&quot;origin_image zh-lightbox-thumb&quot; width=&quot;1177&quot; data-original=&quot;https://pic1.zhimg.com/v2-3067129d92a7ba156ed55bd9c70abe16_r.jpg&quot;/&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p data-pid=&quot;U2kGlt4F&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;zxptkHmf&quot;&gt;完整示例代码&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;import&amp;nbsp;requests
import&amp;nbsp;hashlib
import&amp;nbsp;time

class&amp;nbsp;ZhuanZhuanItemClient:
&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.base_url&amp;nbsp;=&amp;nbsp;&amp;quot;https://open.zhuanzhuan.com/api/item/detail&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_gen_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;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()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_item_detail(self,&amp;nbsp;item_id):
&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;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;quot;item_id&amp;quot;:&amp;nbsp;item_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;params[&amp;quot;sign&amp;quot;]&amp;nbsp;=&amp;nbsp;self._gen_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;requests.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;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;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;if&amp;nbsp;res_json.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;return&amp;nbsp;{&amp;quot;success&amp;quot;:&amp;nbsp;False,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;res_json.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;raw_data&amp;nbsp;=&amp;nbsp;res_json[&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;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;quot;item_id&amp;quot;:&amp;nbsp;raw_data.get(&amp;quot;item_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;quot;title&amp;quot;:&amp;nbsp;raw_data.get(&amp;quot;title&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;quot;price&amp;quot;:&amp;nbsp;float(raw_data.get(&amp;quot;price&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;quot;market_price&amp;quot;:&amp;nbsp;float(raw_data.get(&amp;quot;original_price&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;quot;condition_text&amp;quot;:&amp;nbsp;self._parse_condition(raw_data.get(&amp;quot;condition&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;is_official_verify&amp;quot;:&amp;nbsp;bool(raw_data.get(&amp;quot;has_verify_report&amp;quot;,&amp;nbsp;False)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;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;seller_type&amp;quot;:&amp;nbsp;&amp;quot;merchant&amp;quot;&amp;nbsp;if&amp;nbsp;raw_data.get(&amp;quot;is_business&amp;quot;)&amp;nbsp;else&amp;nbsp;&amp;quot;personal&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;support_warranty&amp;quot;:&amp;nbsp;bool(raw_data.get(&amp;quot;support_warranty&amp;quot;,&amp;nbsp;False)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;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_list&amp;quot;:&amp;nbsp;raw_data.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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;desc&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;success&amp;quot;:&amp;nbsp;True,&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;except&amp;nbsp;requests.exceptions.RequestException&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;success&amp;quot;:&amp;nbsp;False,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;f&amp;quot;网络异常:{str(e)}&amp;quot;,&amp;nbsp;&amp;quot;data&amp;quot;:&amp;nbsp;None}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_parse_condition(self,&amp;nbsp;val):
&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;mapping&amp;nbsp;=&amp;nbsp;{1:&amp;quot;全新&amp;quot;,2:&amp;quot;99新&amp;quot;,3:&amp;quot;95新&amp;quot;,4:&amp;quot;9成新&amp;quot;,5:&amp;quot;8成新及以下&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;mapping.get(val,&amp;nbsp;&amp;quot;未知成色&amp;quot;)

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;ZhuanZhuanItemClient(&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_item_detail(&amp;quot;1234567890&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(ret)&lt;/pre&gt;&lt;/div&gt;&lt;p data-pid=&quot;X0WH9M3D&quot;&gt;核心逻辑解读&lt;/p&gt;&lt;p data-pid=&quot;MUzry9DX&quot;&gt;1. 签名封装：按照平台规则对参数排序拼接密钥生成 md5 签名，&lt;a class=&quot;RichContent-EntityWord css-b7erz1&quot; data-za-not-track-link=&quot;true&quot; data-paste-text=&quot;true&quot; href=&quot;https://zhida.zhihu.com/search?content_id=280655384&amp;content_type=Article&amp;match_order=1&amp;q=%E6%97%B6%E9%97%B4%E6%88%B3&amp;zhida_source=entity&quot; target=&quot;_blank&quot;&gt;时间戳&lt;svg width=&quot;10px&quot; height=&quot;10px&quot; viewbox=&quot;0 0 16 16&quot; class=&quot;ZDI ZDI--FourPointedStar16 css-1dvsrp&quot; fill=&quot;currentColor&quot;&gt;&lt;/svg&gt;&lt;/a&gt;用来防重放攻击。&lt;br/&gt; 2. 成色状态映射：平台返回数字编码，内部做字典映射转换为业务可读成色文本，方便后续统计筛选。&lt;br/&gt; 3. 卖家身份、验机标识提取：区分个人卖家与商家，识别是否附带转转验机报告，这是二手业务非常关键的维度。&lt;br/&gt; 4. 多层异常捕获：区分 HTTP 异常、业务错误码、网络超时，统一返回结构化结果，上层业务不需要大量 try‑except。&lt;/p&gt;&lt;p data-pid=&quot;7Ggq7fvB&quot;&gt;实战踩坑总结&lt;/p&gt;&lt;p data-pid=&quot;w0W8aVQd&quot;&gt;第一，大量二手商品没有原始市场价字段，代码不能直接强取值，必须设置默认 0，否则会触发 KeyError。&lt;br/&gt; 第二，验机报告、质保字段不是所有商品都存在，直接强转布尔可以兼容 key 不存在场景。&lt;br/&gt; 第三，接口存在访问频率限制，循环批量拉取详情时需要增加延时，短时间高频调用会触发限流返回错误码。&lt;br/&gt; 第四，部分下架商品接口不会直接返回 404，而是业务 code 非 0，要优先判断业务返回码，不能只依靠 HTTP 状态码。&lt;/p&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Wed, 05 Aug 2026 17:27:31 +0800</pubDate></item><item><title>京东商品评论接口分页异常修复与结构化解析实战</title><link>https://www.apiproxylog.com/?id=209</link><description>&lt;p&gt;&lt;span id=&quot;content&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;BxBT0J-a&quot;&gt;京东商品评论接口是电商口碑分析、竞品调研、商品质量评估的核心数据源。目前多数开源对接方案仅实现基础请求调用，普遍存在&lt;strong&gt;分页数据重复、追评数据丢失、空页报错、特殊商品无数据&lt;/strong&gt;等生产级问题。本文跳出基础参数讲解的通用套路，聚焦接口高频异常问题，提供修复方案+结构化解析封装代码，适配稳定的线上业务调用场景。&lt;br/&gt;本次对接采用京东联盟官方合规接口 jd.union.open.goods.comment.query，支持获取商品图文评论、追评、星级评分、用户属性等全量数据，兼容全品类商品，规避普通评论接口的权限限制问题。&lt;/p&gt;&lt;p data-pid=&quot;AEuZzMeB&quot;&gt;&lt;br/&gt;一、核心踩坑问题总结&lt;br/&gt;1. 分页参数不规范：未适配接口最大页码限制，超限返回空数据，多页数据重复；2. 字段解析粗糙：默认忽略追评、晒单图片、规格属性等增值字段；3. 无数据容错：商品无评论、商品下架场景直接抛异常，中断程序执行。&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-cca8119d931cd97b2a1c7344d3f369fd_720w.webp&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1155&quot; data-rawheight=&quot;635&quot; data-original-token=&quot;v2-21d876eba8da7e34e0d587749399ff5d&quot; class=&quot;origin_image zh-lightbox-thumb lazy&quot; width=&quot;1155&quot; data-original=&quot;https://pic2.zhimg.com/v2-cca8119d931cd97b2a1c7344d3f369fd_r.jpg&quot; data-actualsrc=&quot;https://pic2.zhimg.com/v2-cca8119d931cd97b2a1c7344d3f369fd_1440w.jpg&quot; height=&quot;635&quot; data-lazy-status=&quot;ok&quot;/&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p data-pid=&quot;kJOApFC7&quot;&gt;&lt;a href=&quot;https://o0b.cn/iiiace&quot; target=&quot;_blank&quot;&gt;点击获取key和secret&lt;/a&gt;&lt;br/&gt;二、优化版完整调用代码&lt;br/&gt;基于Python封装，整合签名校验、分页边界处理、异常捕获、全字段结构化解析，可直接用于生产环境。&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;JdCommentApi:
&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.jd.com/routerjson&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;标准SHA256签名算法
&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_params&amp;nbsp;=&amp;nbsp;sorted(params.items(),&amp;nbsp;key=lambda&amp;nbsp;x:&amp;nbsp;x[0])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sign_str&amp;nbsp;=&amp;nbsp;self.app_secret&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_params)&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.sha256(sign_str.encode(&amp;quot;utf-8&amp;quot;)).hexdigest().upper()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;商品评论分页查询（修复分页异常）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_goods_comment(self,&amp;nbsp;goods_id,&amp;nbsp;page=1,&amp;nbsp;size=10):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;修复：官方最大单页10条，超出强制截断
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;size&amp;nbsp;=&amp;nbsp;10&amp;nbsp;if&amp;nbsp;size&amp;nbsp;&amp;gt;&amp;nbsp;10&amp;nbsp;else&amp;nbsp;size
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;timestamp&amp;nbsp;=&amp;nbsp;int(time.time()&amp;nbsp;*&amp;nbsp;1000)
&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;method&amp;quot;:&amp;nbsp;&amp;quot;jd.union.open.goods.comment.query&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;timestamp&amp;quot;:&amp;nbsp;str(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;format&amp;quot;:&amp;nbsp;&amp;quot;json&amp;quot;,&amp;nbsp;&amp;quot;v&amp;quot;:&amp;nbsp;&amp;quot;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;goodsId&amp;quot;:&amp;nbsp;str(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;page&amp;quot;:&amp;nbsp;page,&amp;nbsp;&amp;quot;pageSize&amp;quot;:&amp;nbsp;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;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;res&amp;nbsp;=&amp;nbsp;requests.post(self.api_url,&amp;nbsp;data=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;res_json&amp;nbsp;=&amp;nbsp;res.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;resp_data&amp;nbsp;=&amp;nbsp;res_json.get(&amp;quot;jd_union_open_goods_comment_query_response&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;if&amp;nbsp;not&amp;nbsp;resp_data.get(&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;&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;resp_data.get(&amp;quot;msg&amp;quot;),&amp;nbsp;&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;&amp;nbsp;comment_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;resp_data.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;comment_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;content&amp;quot;:&amp;nbsp;item.get(&amp;quot;comment&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;score&amp;quot;:&amp;nbsp;item.get(&amp;quot;score&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;spec&amp;quot;:&amp;nbsp;item.get(&amp;quot;skuAttr&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_list&amp;quot;:&amp;nbsp;item.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;after_comment&amp;quot;:&amp;nbsp;item.get(&amp;quot;afterComment&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;create_time&amp;quot;:&amp;nbsp;item.get(&amp;quot;commentTime&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;code&amp;quot;:&amp;nbsp;0,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;&amp;quot;success&amp;quot;,&amp;nbsp;&amp;quot;list&amp;quot;:&amp;nbsp;comment_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;return&amp;nbsp;{&amp;quot;code&amp;quot;:&amp;nbsp;-2,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;f&amp;quot;请求异常：{str(e)}&amp;quot;,&amp;nbsp;&amp;quot;list&amp;quot;:&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;api&amp;nbsp;=&amp;nbsp;JdCommentApi(&amp;quot;你的APP_KEY&amp;quot;,&amp;nbsp;&amp;quot;你的APP_SECRET&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;data&amp;nbsp;=&amp;nbsp;api.get_goods_comment(100012345678,&amp;nbsp;page=1)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(data)&lt;/pre&gt;&lt;/div&gt;&lt;p data-pid=&quot;V1N3QIW9&quot;&gt;&lt;br/&gt;三、关键优化点解析&lt;br/&gt;&lt;strong&gt;1. 分页边界修复&lt;/strong&gt;：官方接口限制单页最大10条数据，代码内置参数强制校验，彻底解决分页错乱、数据重复问题，这是多数通用Demo遗漏的核心规则。&lt;br/&gt;&lt;strong&gt;2. 全维度数据解析&lt;/strong&gt;：主动适配规格属性、晒图、追评、评分等业务核心字段，输出结构化数据，无需二次处理，可直接用于数据分析。&lt;br/&gt;&lt;strong&gt;3. 多层异常容错&lt;/strong&gt;：区分接口业务异常、网络超时、参数错误等场景，统一返回格式，避免程序崩溃，适配批量爬取、定时任务等场景。&lt;/p&gt;&lt;p data-pid=&quot;BonL61dj&quot;&gt;&lt;br/&gt;四、线上使用规范&lt;br/&gt;该接口存在QPS限制，单应用每秒请求不超过2次。批量获取多页数据时，建议添加300ms间隔延时，同时过滤重复评论数据。禁止高频暴力请求，否则会触发接口限流，导致短期封禁权限。&lt;/p&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Tue, 04 Aug 2026 17:16:36 +0800</pubDate></item><item><title>京东关键词搜索接口规范化对接与高频问题优化实践</title><link>https://www.apiproxylog.com/?id=208</link><description>&lt;p&gt;&lt;span id=&quot;content&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;Lsi66IR1&quot;&gt;在电商数据抓取、商品比价、品类数据分析场景中，京东关键词搜索接口是高频复用的核心能力。目前多数对接方案仅实现基础请求调用，普遍存在签名不规范、参数适配缺失、异常容错不足、高频限流报错等问题。本文摒弃基础入门式讲解，聚焦&lt;strong&gt;生产级规范化对接&lt;/strong&gt;，解决接口鉴权失败、结果乱序、风控拦截等核心痛点，提供可直接落地的封装代码。&lt;/p&gt;&lt;p data-pid=&quot;9SsZN0Ra&quot;&gt;&lt;br/&gt;一、接口核心特性与对接难点&lt;br/&gt;本次对接基于京东开放平台商品搜索核心接口（jd.union.open.goods.query），采用POST请求方式，核心难点集中三点：一是接口签名需严格参数排序+毫秒级时间戳，格式错误直接鉴权失败；二是关键词需URL编码适配中文检索，否则返回空数据；三是高频请求无容错机制，极易触发平台限流风控。&lt;br/&gt;区别于通用demo，本文方案新增参数校验、异常重试、结果过滤三大能力，适配生产环境稳定调用需求。&lt;/p&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-cb8c8f2a5cd9e9b6a73178ab51aa2e85_720w.jpg&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1164&quot; data-rawheight=&quot;659&quot; data-original-token=&quot;v2-2ed46d32f0d9cfd566afc243fdf60bbc&quot; class=&quot;origin_image zh-lightbox-thumb lazy&quot; width=&quot;1164&quot; data-original=&quot;https://pic4.zhimg.com/v2-cb8c8f2a5cd9e9b6a73178ab51aa2e85_r.jpg&quot; data-actualsrc=&quot;https://pic4.zhimg.com/v2-cb8c8f2a5cd9e9b6a73178ab51aa2e85_1440w.jpg&quot; height=&quot;659&quot; data-lazy-status=&quot;ok&quot;/&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p data-pid=&quot;IgDBuMxJ&quot;&gt;&lt;a href=&quot;https://o0b.cn/iiiace&quot; target=&quot;_blank&quot;&gt;点击获取key和secret&lt;/a&gt;&lt;br/&gt;二、生产级接口封装代码&lt;br/&gt;基于Python实现轻量化封装，整合签名生成、参数校验、异常捕获、数据精简解析，代码简洁无冗余，兼容Python3.7+版本。&lt;/p&gt;&lt;p class=&quot;ztext-empty-paragraph&quot;&gt;&lt;br/&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
from&amp;nbsp;urllib.parse&amp;nbsp;import&amp;nbsp;quote

class&amp;nbsp;JdSearchApi:
&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.url&amp;nbsp;=&amp;nbsp;&amp;quot;https://api.jd.com/routerjson&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.timeout&amp;nbsp;=&amp;nbsp;10

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;标准化SHA256签名生成
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_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;key=lambda&amp;nbsp;x:&amp;nbsp;x[0])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sign_str&amp;nbsp;=&amp;nbsp;self.app_secret&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.sha256(sign_str.encode()).hexdigest().upper()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;关键词搜索核心方法
&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;sort=3):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;中文关键词编码适配
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;encode_key&amp;nbsp;=&amp;nbsp;quote(keyword,&amp;nbsp;encoding=&amp;quot;utf-8&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;13位毫秒级时间戳
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;timestamp&amp;nbsp;=&amp;nbsp;int(time.time()&amp;nbsp;*&amp;nbsp;1000)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;nbsp;=&amp;nbsp;{
&amp;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;method&amp;quot;:&amp;nbsp;&amp;quot;jd.union.open.goods.query&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;timestamp&amp;quot;:&amp;nbsp;str(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;format&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;v&amp;quot;:&amp;nbsp;&amp;quot;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;keyword&amp;quot;:&amp;nbsp;encode_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;pageIndex&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;quot;sortType&amp;quot;:&amp;nbsp;sort
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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.get_sign(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;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;res&amp;nbsp;=&amp;nbsp;requests.post(self.url,&amp;nbsp;data=params,&amp;nbsp;timeout=self.timeout)
&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;res.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;res_data.get(&amp;quot;code&amp;quot;)&amp;nbsp;!=&amp;nbsp;&amp;quot;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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;status&amp;quot;:&amp;nbsp;0,&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;[]}
&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;1,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;&amp;quot;success&amp;quot;,&amp;nbsp;&amp;quot;data&amp;quot;:&amp;nbsp;res_data.get(&amp;quot;jd_union_open_goods_query_response&amp;quot;,&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;return&amp;nbsp;{&amp;quot;status&amp;quot;:&amp;nbsp;0,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;f&amp;quot;请求异常：{str(e)}&amp;quot;,&amp;nbsp;&amp;quot;data&amp;quot;:&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;api&amp;nbsp;=&amp;nbsp;JdSearchApi(&amp;quot;你的APP_KEY&amp;quot;,&amp;nbsp;&amp;quot;你的APP_SECRET&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;api.search_goods(&amp;quot;无线蓝牙耳机&amp;quot;,&amp;nbsp;page=1,&amp;nbsp;page_size=10)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(result)&lt;/pre&gt;&lt;/div&gt;&lt;p data-pid=&quot;mkYjJx90&quot;&gt;&lt;br/&gt;三、关键优化点与避坑解析&lt;br/&gt;1. &lt;strong&gt;签名机制标准化&lt;/strong&gt;：严格按照参数ASCII码升序拼接，采用SHA256加密，规避大部分鉴权报错，适配最新接口校验规则。&lt;br/&gt;2. &lt;strong&gt;参数精准适配&lt;/strong&gt;：强制使用13位毫秒时间戳、中文关键词URL编码，解决空返回、参数非法等高频问题。&lt;br/&gt;3. &lt;strong&gt;健壮性优化&lt;/strong&gt;：内置超时控制、异常捕获、状态码校验，区分网络异常和接口业务异常，便于问题排查。&lt;/p&gt;&lt;p data-pid=&quot;fFJhE7Az&quot;&gt;&lt;br/&gt;四、生产环境使用建议&lt;br/&gt;接口调用需严格控制QPS，单账号每秒请求不超过3次，高频场景可增加请求间隔、配置简易重试机制；同时建议缓存热门关键词检索结果，减少重复请求，规避平台风控限制，大幅提升接口调用稳定性。&lt;/p&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Mon, 03 Aug 2026 17:17:47 +0800</pubDate></item><item><title>京东商品详情接口工程实践：区域价格适配 + 多规格 SKU 归一化 + 分级重试方案（Python 实现）</title><link>https://www.apiproxylog.com/?id=207</link><description>&lt;p&gt;&lt;span id=&quot;content&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;NA8Bt4jW&quot;&gt;前言&lt;/p&gt;&lt;p data-pid=&quot;5xhxPYCj&quot;&gt;市面上大多数京东商品详情接口教程仅实现基础调用，只抓取标题、售价等浅层信息，忽略京东平台两大核心特性：商品价格、库存跟随收货区域动态变化，同时多 SKU 原始数据结构杂乱，很难直接投入业务系统。&lt;br/&gt; 本文不重复基础签名教学，重点解决业务落地痛点：封装区域编码参数、原始 SKU 数据归一化处理、指数退避重试机制，适配比价监控、商品铺货场景。所有代码内置数据清洗逻辑，可直接改造接入项目。&lt;/p&gt;&lt;p data-pid=&quot;7wxfc8so&quot;&gt;前置准备&lt;/p&gt;&lt;p data-pid=&quot;YMf53ClO&quot;&gt;提前入驻京东开放平台，创建应用获取&lt;code&gt;app_key&lt;/code&gt;、&lt;code&gt;app_secret&lt;/code&gt;，开通商品详情接口权限。需要注意：京东商品以 SKU 为唯一标识，而非 SPU，调用接口必须传入有效的 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://picx.zhimg.com/80/v2-da5b0987ccf80f63f83af33268c9b1a7_720w.jpg&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1155&quot; data-rawheight=&quot;645&quot; data-original-token=&quot;v2-ff7cd17ecdb1d6476b5e416c8f67fcdd&quot; class=&quot;origin_image zh-lightbox-thumb lazy&quot; width=&quot;1155&quot; data-original=&quot;https://picx.zhimg.com/v2-da5b0987ccf80f63f83af33268c9b1a7_r.jpg&quot; data-actualsrc=&quot;https://picx.zhimg.com/v2-da5b0987ccf80f63f83af33268c9b1a7_1440w.jpg&quot; height=&quot;645&quot; data-lazy-status=&quot;ok&quot;/&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p data-pid=&quot;Xn0mwq8B&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;x0eNnI4l&quot;&gt;完整 Python 代码实现&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
import&amp;nbsp;json

class&amp;nbsp;JdItemDetailClient:
&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.jd.com/routerjson&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;&amp;nbsp;def&amp;nbsp;build_sign(self,&amp;nbsp;param_dict):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sorted_param&amp;nbsp;=&amp;nbsp;sorted(param_dict.items(),&amp;nbsp;key=lambda&amp;nbsp;x:&amp;nbsp;x[0])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sign_raw&amp;nbsp;=&amp;nbsp;self.app_secret
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;k,&amp;nbsp;v&amp;nbsp;in&amp;nbsp;sorted_param:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sign_raw&amp;nbsp;+=&amp;nbsp;f&amp;quot;{k}{v}&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sign_raw&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;#&amp;nbsp;获取商品详情
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_item_detail(self,&amp;nbsp;sku_id,&amp;nbsp;area_code=&amp;quot;1_72_2799_0&amp;quot;,&amp;nbsp;max_retry=3):
&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;method&amp;quot;:&amp;nbsp;&amp;quot;jingdong.item.base.info.get&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;timestamp&amp;quot;:&amp;nbsp;time.strftime(&amp;quot;%Y-%m-%d&amp;nbsp;%H:%M:%S&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;v&amp;quot;:&amp;nbsp;&amp;quot;2.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;format&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;360buy_param_json&amp;quot;:&amp;nbsp;json.dumps({&amp;quot;skuId&amp;quot;:&amp;nbsp;sku_id,&amp;nbsp;&amp;quot;area&amp;quot;:&amp;nbsp;area_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;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;retry_count&amp;nbsp;=&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while&amp;nbsp;retry_count&amp;nbsp;&amp;lt;&amp;nbsp;max_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.post(self.api_url,&amp;nbsp;data=params,&amp;nbsp;timeout=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;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;&amp;quot;jingdong_item_base_info_response&amp;quot;&amp;nbsp;in&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;data&amp;nbsp;=&amp;nbsp;result[&amp;quot;jingdong_item_base_info_response&amp;quot;][&amp;quot;result&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;clean_data&amp;nbsp;=&amp;nbsp;self.data_normalize(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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;success&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;data&amp;quot;:&amp;nbsp;clean_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;return&amp;nbsp;{&amp;quot;success&amp;quot;:&amp;nbsp;False,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;result.get(&amp;quot;error_response&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;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;retry_count&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;time.sleep(2&amp;nbsp;**&amp;nbsp;retry_count)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;success&amp;quot;:&amp;nbsp;False,&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;data_normalize(self,&amp;nbsp;raw):
&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;sku_id&amp;quot;:&amp;nbsp;raw.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;quot;title&amp;quot;:&amp;nbsp;raw.get(&amp;quot;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;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;quot;is_self&amp;quot;:&amp;nbsp;raw.get(&amp;quot;isJdSelf&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;price&amp;quot;:&amp;nbsp;raw.get(&amp;quot;jdPrice&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_price&amp;quot;:&amp;nbsp;raw.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;quot;stock_state&amp;quot;:&amp;nbsp;raw.get(&amp;quot;stockState&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_image&amp;quot;:&amp;nbsp;raw.get(&amp;quot;imageUrl&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;spec_list&amp;quot;:&amp;nbsp;raw.get(&amp;quot;skuSpecList&amp;quot;,&amp;nbsp;[])
&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;JdItemDetailClient(&amp;quot;你的app_key&amp;quot;,&amp;nbsp;&amp;quot;你的app_secret&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;res&amp;nbsp;=&amp;nbsp;client.get_item_detail(&amp;quot;100012345678&amp;quot;,&amp;nbsp;area_code=&amp;quot;1_72_2799_0&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(json.dumps(res,&amp;nbsp;ensure_ascii=False,&amp;nbsp;indent=2))&lt;/pre&gt;&lt;/div&gt;&lt;p data-pid=&quot;GA2xT9Br&quot;&gt;核心方案解析&lt;/p&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;区域价格适配&lt;/strong&gt;&lt;br/&gt; 增加&lt;code&gt;area_code&lt;/code&gt;区域参数，不同省市仓储库存、运费、活动价存在差异。默认填入北京区域编码，业务系统可根据用户收货地址动态切换，避免展示价格和实际下单价格不一致。&lt;br/&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;SKU 归一化清洗&lt;/strong&gt;&lt;br/&gt; 原始接口返回规格数据嵌套层级深，新增&lt;code&gt;data_normalize&lt;/code&gt;方法统一输出结构。后续对接数据库、前端页面无需重复解析 JSON，降低维护成本。&lt;br/&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;指数退避重试&lt;/strong&gt;&lt;br/&gt; 针对接口限流、网络波动问题，采用指数延时重试，相比固定休眠，能够有效减少高频重试引发的风控拦截。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Sun, 02 Aug 2026 17:11:20 +0800</pubDate></item><item><title>微店商品详情API对接实战：权限自适应校验+私有商品兼容+结构化数据落地（Python全新方案）</title><link>https://www.apiproxylog.com/?id=206</link><description>&lt;p&gt;&lt;span id=&quot;content&quot;&gt;&lt;p data-first-child=&quot;&quot; data-pid=&quot;4vs9J-75&quot;&gt;一、开发背景与通用痛点&lt;br/&gt;在私域店铺运维、商品数据归档、分销数据统计系统开发中，微店商品详情数据是核心数据源。市面上多数对接教程仅适配公开商品查询，存在明显短板：无法兼容私密商品、未做权限分级校验、返回数据杂乱无规则、无异常场景细分处理。同时微店开放平台接口鉴权逻辑轻量但权限管控严格，未做适配的代码极易出现偶发请求失败、数据缺失问题。本文摒弃传统基础调用写法，从生产适配角度重构对接方案，重点解决权限兼容、私有商品拦截、数据规整清洗三大核心问题。&lt;/p&gt;&lt;p data-pid=&quot;j_yLGnbY&quot;&gt;&lt;br/&gt;二、本文核心创新点（差异化）&lt;br/&gt;1. &lt;strong&gt;权限自适应校验机制&lt;/strong&gt;：自动区分Token过期、权限不足、商品私有、ID无效四类报错，精准定位对接故障，区别于统一异常捕获的简陋写法。&lt;br/&gt;2. &lt;strong&gt;公私商品兼容处理&lt;/strong&gt;：专门适配微店独有私密商品、仅粉丝可见商品场景，提前拦截无权限数据，避免程序报错。&lt;br/&gt;3. &lt;strong&gt;轻量化数据规整&lt;/strong&gt;：剔除接口冗余字段，统一数值类型转换，销量、库存、价格空值兜底，无需二次数据处理即可入库。&lt;br/&gt;4. &lt;strong&gt;极简高可用封装&lt;/strong&gt;：剥离冗余逻辑，保留生产核心能力，低QPS适配微店接口限流规则，支持长期定时轮询调用。&lt;/p&gt;&lt;p data-pid=&quot;CxlqcsMc&quot;&gt;&lt;br/&gt;三、接口接入规范&lt;br/&gt;采用微店官方合规商品详情查询接口，接口采用
 AccessToken 
单点鉴权，无需复杂加密签名，适配轻量化后端服务开发。接口区分商家自有商品与公开商品，仅授权账号可读取私有商品完整数据，未授权仅能获取基础公开信息，这是微店区别于其他电商平台的核心权限特性。官方限制单账号QPS≤2，批量查询需严格控制请求间隔。&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-bccd0409e6244628be064aba6b568cb8_720w.webp&quot; data-caption=&quot;&quot; data-size=&quot;normal&quot; data-rawwidth=&quot;1165&quot; data-rawheight=&quot;588&quot; data-original-token=&quot;v2-8f9220aec567c299f39c967f69a30fa2&quot; class=&quot;origin_image zh-lightbox-thumb lazy&quot; width=&quot;1165&quot; data-original=&quot;https://pic1.zhimg.com/v2-bccd0409e6244628be064aba6b568cb8_r.jpg&quot; data-actualsrc=&quot;https://pic1.zhimg.com/v2-bccd0409e6244628be064aba6b568cb8_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;UA_YayrC&quot;&gt;&lt;a href=&quot;https://o0b.cn/iiiace&quot; target=&quot;_blank&quot;&gt;点击获取key和secret&lt;/a&gt;&lt;br/&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;json

class&amp;nbsp;NewWeidianDetailApi:
&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;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.strip()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.api_gateway&amp;nbsp;=&amp;nbsp;&amp;quot;https://open.weidian.com/v1/item/detail&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.http&amp;nbsp;=&amp;nbsp;requests.Session()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;parse_error(self,&amp;nbsp;code:&amp;nbsp;int,&amp;nbsp;msg:&amp;nbsp;str):
&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;err_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;1001:&amp;nbsp;&amp;quot;AccessToken过期或无效&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;1002:&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;2003:&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;4004:&amp;nbsp;&amp;quot;商品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;return&amp;nbsp;err_map.get(code,&amp;nbsp;f&amp;quot;未知异常：{msg}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_detail(self,&amp;nbsp;item_id:&amp;nbsp;str):
&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;payload&amp;nbsp;=&amp;nbsp;{
&amp;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;access_token&amp;quot;:&amp;nbsp;self.token,
&amp;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_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;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;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;res&amp;nbsp;=&amp;nbsp;self.http.get(self.api_gateway,&amp;nbsp;params=payload,&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;res_data&amp;nbsp;=&amp;nbsp;res.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;res_data.get(&amp;quot;status&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;err_msg&amp;nbsp;=&amp;nbsp;self.parse_error(res_data.get(&amp;quot;code&amp;quot;,&amp;nbsp;0),&amp;nbsp;res_data.get(&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;state&amp;quot;:&amp;nbsp;False,&amp;nbsp;&amp;quot;message&amp;quot;:&amp;nbsp;err_msg,&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;raw&amp;nbsp;=&amp;nbsp;res_data.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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;format_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;&amp;nbsp;&amp;nbsp;&amp;quot;goods_id&amp;quot;:&amp;nbsp;raw.get(&amp;quot;item_id&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;quot;goods_title&amp;quot;:&amp;nbsp;raw.get(&amp;quot;title&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;quot;sell_price&amp;quot;:&amp;nbsp;float(raw.get(&amp;quot;price&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;quot;stock_num&amp;quot;:&amp;nbsp;int(raw.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;quot;sales_volume&amp;quot;:&amp;nbsp;int(raw.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;quot;cover_img&amp;quot;:&amp;nbsp;raw.get(&amp;quot;cover&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;quot;is_private_item&amp;quot;:&amp;nbsp;bool(raw.get(&amp;quot;is_private&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;quot;create_time&amp;quot;:&amp;nbsp;raw.get(&amp;quot;create_time&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;time.sleep(1.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;{&amp;quot;state&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;message&amp;quot;:&amp;nbsp;&amp;quot;查询成功&amp;quot;,&amp;nbsp;&amp;quot;data&amp;quot;:&amp;nbsp;format_data}

&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;state&amp;quot;:&amp;nbsp;False,&amp;nbsp;&amp;quot;message&amp;quot;:&amp;nbsp;f&amp;quot;网络请求异常：{str(e)}&amp;quot;,&amp;nbsp;&amp;quot;data&amp;quot;:&amp;nbsp;None}

#&amp;nbsp;调用示例
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;NewWeidianDetailApi(token=&amp;quot;你的微店开放平台AccessToken&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;api.get_detail(item_id=&amp;quot;目标商品ID&amp;quot;)
&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;K4jK8X8M&quot;&gt;&lt;br/&gt;五、生产对接关键避坑点&lt;br/&gt;微店Token有效期较短，定时同步业务需增加定时刷新机制，避免批量查询中途鉴权失效。平台对私有商品权限管控严格，非店铺授权账号无法读取库存、销量核心数据，属于正常权限限制，非接口Bug。必须严格遵循1秒以上请求间隔，高频调用会触发临时封禁，时长可达数小时。所有数值字段必须强制类型转换，接口空返回直接赋值会导致程序类型报错。&lt;/p&gt;&lt;p data-pid=&quot;NbYHBkBF&quot;&gt;&lt;br/&gt;六、合规说明与总结&lt;br/&gt;本文基于微店官方开放平台合规接口开发，无抓包、逆向、违规采集行为，仅用于商家自有店铺数据归档、私域运营数据分析等合法场景。全文采用&lt;strong&gt;权限细分+场景兼容+数据标准化&lt;/strong&gt;全新思路，区别于网络同质化基础调用代码，解决了生产环境下私有商品适配、报错模糊、数据错乱等核心难题。代码轻量化、零冗余，可直接集成各类私域运营后台，适配长期稳定自动化调用需求。&lt;/p&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Fri, 31 Jul 2026 17:09:29 +0800</pubDate></item></channel></rss>