手把手教你接入亚马逊 API:开发商品详情实时数据采集接口

194 阅读6分钟

一、引言:为什么需要接入亚马逊 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:卖家账号 ID
    • Marketplace ID:目标站点 ID(如美国站为ATVPDKIKX0DER

3. 安装必要的 Python 库

 

pip install requests pyjwt python-dateutil

三、核心流程:API 认证与数据获取

1. 认证机制解析

亚马逊 SP-API 使用OAuth 2.0认证体系,流程如下:

  1. 使用Refresh Token获取Access Token(有效期 24 小时)
  2. 使用Access Token调用 API 接口
  3. 令牌过期前通过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 的接入流程和商品数据采集方法。实际应用中,你可以:

  1. 扩展数据类型:获取评论数据(/reviews/2021-01-01/reviews)、库存数据(/fba/inventory/v1/summaries
  2. 构建定时任务:使用crontabAirflow实现数据定时采集
  3. 开发可视化界面:结合FlaskDjango搭建数据管理平台

注意:亚马逊 API 政策可能更新,建议定期查阅api文档获取最新规范,避免因接口变动导致程序失效。