一、引言:为什么需要接入亚马逊 API
在电商领域,实时获取商品详情数据是市场分析、竞品监控、价格策略制定的核心需求。通过亚马逊 API,开发者可以合法、高效地获取商品标题、价格、库存、评论等关键信息,为电商运营、数据分析和自动化工具开发提供数据支持。本文将从 0 到 1 教你搭建一个完整的亚马逊商品数据采集接口,适用于 Python 开发者。
二、准备工作:注册与认证流程
1. 注册亚马逊开发者账号
-
访问并注册****账号****
pip install requests pyjwt python-dateutil -
选择 Selling Partner API (SP-API) 服务,这是亚马逊最新的卖家 API 体系
2. 创建应用并获取凭证
-
登录进入 API 页面
-
创建新应用,填写应用名称、用途描述等信息
-
获取以下关键凭证:
Client ID:应用唯一标识Client Secret:应用密钥Refresh Token:用于刷新访问令牌Seller ID:卖家账号 IDMarketplace ID:目标站点 ID(如美国站为ATVPDKIKX0DER)
3. 安装必要的 Python 库
pip install requests pyjwt python-dateutil
三、核心流程:API 认证与数据获取
1. 认证机制解析
亚马逊 SP-API 使用OAuth 2.0认证体系,流程如下:
- 使用
Refresh Token获取Access Token(有效期 24 小时) - 使用
Access Token调用 API 接口 - 令牌过期前通过
Refresh Token刷新
2. 认证模块代码实现
import requests
import jwt
import time
import datetime
from dateutil import tz
class AmazonAPIClient:
def __init__(self, client_id, client_secret, refresh_token, seller_id, marketplace_id):
self.client_id = client_id
self.client_secret = client_secret
self.refresh_token = refresh_token
self.seller_id = seller_id
self.marketplace_id = marketplace_id
self.access_token = None
self.token_expiry = None
def get_access_token(self):
"""获取或刷新访问令牌"""
# 检查令牌是否有效
if self.access_token and self.token_expiry and self.token_expiry > datetime.datetime.now():
return self.access_token
# 构建认证请求
url = "https://api.amazon.com/auth/o2/token"
payload = {
"grant_type": "refresh_token",
"client_id": self.client_id,
"client_secret": self.client_secret,
"refresh_token": self.refresh_token
}
try:
response = requests.post(url, data=payload)
response.raise_for_status()
token_data = response.json()
# 存储令牌及过期时间(减去5分钟避免刚好过期)
self.access_token = token_data["access_token"]
expires_in = token_data["expires_in"] - 300 # 300秒=5分钟
self.token_expiry = datetime.datetime.now() + datetime.timedelta(seconds=expires_in)
return self.access_token
except Exception as e:
print(f"获取令牌失败: {e}")
raise
def generate_headers(self, endpoint):
"""生成API请求头(包含签名和认证信息)"""
# 此处简化处理,实际生产环境需按亚马逊规范生成签名
# 完整签名规范参考:https://github.com/amzn/selling-partner-api-docs/blob/main/guides/developer-guide/SellingPartnerApiDeveloperGuide.md#authenticating-requests
return {
"Authorization": f"Bearer {self.get_access_token()}",
"Content-Type": "application/json",
"x-amz-access-token": self.get_access_token()
}
四、商品详情接口开发
1. 接口端点与参数
-
端点:
/products/v0/itemTypes/{asin} -
请求方式:
GET -
必需参数:
ASIN:亚马逊标准识别码(如B0756CYW3Z)marketplaceIds:目标站点 ID(如ATVPDKIKX0DER)
2. 数据采集模块实现
def get_product_details(self, asin):
"""获取单个商品详情"""
endpoint = f"https://sellingpartnerapi-na.amazon.com/products/v0/itemTypes/{asin}"
headers = self.generate_headers(endpoint)
# 构建请求参数
params = {
"marketplaceIds": self.marketplace_id,
"includedData": "images,price,description,attributes" # 指定返回数据类型
}
try:
response = requests.get(endpoint, headers=headers, params=params)
response.raise_for_status()
# 解析响应数据
product_data = response.json()
return self._parse_product_data(product_data)
except requests.exceptions.HTTPError as e:
if response.status_code == 429:
print("请求频率过高,触发限流,等待中...")
retry_after = int(response.headers.get("Retry-After", 60))
time.sleep(retry_after)
return self.get_product_details(asin) # 递归重试
print(f"API请求失败,状态码: {response.status_code}, 内容: {response.text}")
raise
except Exception as e:
print(f"获取商品详情失败: {e}")
raise
def _parse_product_data(self, data):
"""解析API返回的商品数据"""
try:
item = data.get("item", {})
attributes = item.get("attributes", {})
images = item.get("images", {}).get("primary", {})
price = item.get("price", {})
return {
"asin": item.get("asin"),
"title": attributes.get("title", "未知标题"),
"brand": attributes.get("brand", "未知品牌"),
"description": attributes.get("description", ""),
"image_url": images.get("large", {}).get("url", ""),
"current_price": price.get("current", {}).get("amount", 0),
"currency": price.get("current", {}).get("currencyCode", "USD"),
"update_time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
except Exception as e:
print(f"数据解析失败: {e}")
return {"error": "数据解析异常"}
五、批量采集与异常处理
1. 批量获取商品数据
def batch_get_products(self, asin_list, batch_size=20):
"""批量获取多个商品详情(亚马逊API有批量限制)"""
all_products = []
for i in range(0, len(asin_list), batch_size):
batch_asins = asin_list[i:i+batch_size]
print(f"正在获取第{i+1}-{min(i+batch_size, len(asin_list))}个商品...")
# 构建批量请求(亚马逊SP-API批量端点需按规范拼接)
# 注意:不同API版本的批量接口格式不同,此处以products/v0为例
endpoint = "https://sellingpartnerapi-na.amazon.com/products/v0/itemTypes"
headers = self.generate_headers(endpoint)
params = {
"marketplaceIds": self.marketplace_id,
"includedData": "images,price,description,attributes",
"asins": ",".join(batch_asins)
}
try:
response = requests.get(endpoint, headers=headers, params=params)
response.raise_for_status()
batch_data = response.json()
# 解析每个商品数据
for item in batch_data.get("items", []):
parsed_item = self._parse_product_data({"item": item})
all_products.append(parsed_item)
# 处理可能的限流
if "errors" in batch_data:
for error in batch_data["errors"]:
if error.get("code") == "TooManyRequests":
print(f"批量请求触发限流,错误信息: {error.get('message')}")
time.sleep(60) # 等待1分钟后重试
return self.batch_get_products(asin_list) # 递归重试
except Exception as e:
print(f"批量获取失败: {e}")
return all_products
2. 完整异常处理机制
def handle_api_error(self, response):
"""统一处理API错误响应"""
try:
error_data = response.json()
errors = error_data.get("errors", [])
for error in errors:
error_code = error.get("code")
error_msg = error.get("message")
if error_code == "Unauthorized":
print("认证失败,刷新令牌并重试...")
self.access_token = None # 清除旧令牌
return True # 允许重试
elif error_code == "TooManyRequests":
print(f"请求过于频繁,错误信息: {error_msg}")
retry_after = int(response.headers.get("Retry-After", 60))
print(f"等待{retry_after}秒后重试...")
time.sleep(retry_after)
return True # 允许重试
else:
print(f"API错误,代码: {error_code}, 信息: {error_msg}")
return False # 不重试
except:
print(f"未知错误响应: {response.text}")
return False
六、实际应用示例
1. 初始化客户端
# 替换为你的实际凭证
client = AmazonAPIClient(
client_id="你的Client ID",
client_secret="你的Client Secret",
refresh_token="你的Refresh Token",
seller_id="你的Seller ID",
marketplace_id="ATVPDKIKX0DER" # 美国站
)
2. 获取单个商品详情
# 查询iPhone 14的商品信息
asin = "B09G9T3K15"
product = client.get_product_details(asin)
print(f"商品标题: {product['title']}")
print(f"当前价格: {product['current_price']} {product['currency']}")
3. 批量查询多个商品
# 批量查询多个ASIN
asin_list = ["B09G9T3K15", "B08N5W3825", "B07XVF5Z8Q"]
products = client.batch_get_products(asin_list)
# 保存到CSV文件
import pandas as pd
df = pd.DataFrame(products)
df.to_csv("amazon_products.csv", index=False, encoding="utf-8-sig")
七、API 使用注意事项
1. 亚马逊 API 限制
- 请求频率:不同 API 级别有不同限制(如基础版每秒 10 请求)
- 数据使用:禁止爬取非公开数据、恶意刷新或用于竞品作弊
- 合规性:需在应用中声明数据用途,遵守亚马逊卖家协议
2. 优化建议
- 缓存机制:对非实时数据设置缓存(如 24 小时),减少请求次数
- 异步处理:使用
asyncio或线程池处理批量请求,提高效率 - 代理 IP:若触发区域限制,可使用合规代理 IP(需注意亚马逊政策)
- 日志记录:记录请求时间、结果和错误,便于问题排查
八、总结与扩展方向
通过本文的步骤,你已掌握亚马逊 SP-API 的接入流程和商品数据采集方法。实际应用中,你可以:
- 扩展数据类型:获取评论数据(
/reviews/2021-01-01/reviews)、库存数据(/fba/inventory/v1/summaries) - 构建定时任务:使用
crontab或Airflow实现数据定时采集 - 开发可视化界面:结合
Flask或Django搭建数据管理平台
注意:亚马逊 API 政策可能更新,建议定期查阅api文档获取最新规范,避免因接口变动导致程序失效。