跨境电商速卖通(AliExpress)数据采集与 API 接口接入全方案

速卖通作为全球主流跨境电商平台,其开放平台 API 是合规采集商品价格、库存、促销等核心数据的首选方式;针对无接口权限场景,也可通过合规爬虫补充采集。以下从API 接口接入(核心)、爬虫采集(补充)、数据处理三个维度完整说明。

一、速卖通开放平台 API 核心特性(补充至跨境电商平台体系)
维度核心特性
认证方式基于 App Key + App Secret 的 HMAC-SHA256 签名认证(部分接口支持 OAuth2.0)
核心接口1. 商品详情:aliexpress.product.redefining.getproductdetail2. 价格 / 促销:aliexpress.offer.redefining.getpricelist3. 运费模板:aliexpress.logistics.redefining.getfreighttemplate4. SKU 信息:aliexpress.product.redefining.getskuinfolist
调用限制单 App 每日调用限额(普通开发者约 10 万次 / 天),单接口 QPS≤5,IP 无白名单但高频调用易限流
数据特点支持多站点(如美国、俄罗斯、西班牙站)、多币种(USD/EUR/RUB 等)、多语言,价格含折扣 / 运费拆分
合规要求需完成企业开发者认证,遵守《速卖通开放平台服务协议》,禁止商用数据倒卖
二、速卖通 API 接口接入(Python 实战)
2.1 前置准备
  1. 账号与权限申请
    • 登录速卖通开放平台,完成企业主体认证(需提供营业执照、跨境电商资质);
    • 创建应用,申请上述核心接口的调用权限(审核周期约 1-3 个工作日);
    • 记录关键信息:App KeyApp Secret、应用授权码(若需 OAuth2.0)。
  2. 依赖库安装

    bash

    运行

    pip install requests pycryptodome python-dotenv  # 签名/请求/环境变量管理
    
2.2 Python 封装速卖通 API 客户端(核心代码)

速卖通 API 签名需严格遵循 HMAC-SHA256 算法,且参数需按 ASCII 升序排序,以下是可直接复用的客户端:

python

运行

import requests
import time
import hmac
import hashlib
import json
from urllib.parse import urlencode, quote
from dotenv import load_dotenv
import os

# 加载环境变量(避免硬编码AppKey/Secret)
load_dotenv()
APP_KEY = os.getenv("ALI_APP_KEY")
APP_SECRET = os.getenv("ALI_APP_SECRET")
API_GATEWAY = "https://openapi.aliexpress.com/api"

class AliExpressAPIClient:
    def __init__(self, app_key, app_secret):
        self.app_key = app_key
        self.app_secret = app_secret
        self.session = requests.Session()
        self.session.headers.update({
            "Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AliExpressAPI/1.0"
        })

    def generate_sign(self, params):
        """生成速卖通API签名(HMAC-SHA256)"""
        # 1. 参数按ASCII升序排序
        sorted_params = sorted(params.items(), key=lambda x: x[0])
        # 2. 拼接为"key=value"格式(value需URL编码)
        sign_str = "&".join([f"{k}={quote(str(v), safe='')}" for k, v in sorted_params])
        # 3. HMAC-SHA256加密 + Base64编码
        sign = hmac.new(
            self.app_secret.encode("utf-8"),
            sign_str.encode("utf-8"),
            hashlib.sha256
        ).digest()
        return sign.hex().upper()  # 转为十六进制大写

    def request(self, api_path, params, method="POST", retry=3, delay=2):
        """发送API请求(含重试机制)"""
        try:
            # 补充公共参数
            public_params = {
                "app_key": self.app_key,
                "timestamp": int(time.time() * 1000),  # 毫秒级时间戳
                "format": "json",
                "v": "2.0",
                "sign_method": "hmac-sha256"
            }
            # 合并公共参数与业务参数
            all_params = {**public_params, **params}
            # 生成签名
            all_params["sign"] = self.generate_sign(all_params)

            # 发送请求
            if method == "GET":
                url = f"{API_GATEWAY}{api_path}?{urlencode(all_params)}"
                response = self.session.get(url, timeout=15)
            else:
                url = f"{API_GATEWAY}{api_path}"
                response = self.session.post(url, data=all_params, timeout=15)
            
            response.raise_for_status()
            result = response.json()
            
            # 处理接口错误
            if result.get("error_code"):
                raise Exception(f"API错误:{result['error_code']} - {result['error_message']}")
            return result

        except Exception as e:
            if retry > 0:
                time.sleep(delay)  # 指数退避重试
                return self.request(api_path, params, method, retry-1, delay*2)
            raise Exception(f"调用失败:{str(e)}")

    def get_product_detail(self, product_id, country="US", currency="USD"):
        """获取商品详情(含基础价格、名称、SKU)"""
        api_path = "/aliexpress/product/redefining/getproductdetail"
        params = {
            "product_id": product_id,  # 速卖通商品ID(从商品页URL提取)
            "country": country,       # 站点国家编码(US/ES/RU等)
            "currency": currency      # 目标币种
        }
        return self.request(api_path, params)

    def get_product_price(self, product_id, sku_id=""):
        """获取商品实时价格(含促销价、折扣)"""
        api_path = "/aliexpress/offer/redefining/getpricelist"
        params = {
            "product_id": product_id,
            "sku_id": sku_id  # 空则返回默认SKU价格
        }
        return self.request(api_path, params)

    def get_freight_template(self, template_id, country="US"):
        """解析运费模板(计算商品+运费总成本)"""
        api_path = "/aliexpress/logistics/redefining/getfreighttemplate"
        params = {
            "template_id": template_id,
            "country": country
        }
        return self.request(api_path, params)

# 调用示例
if __name__ == "__main__":
    client = AliExpressAPIClient(APP_KEY, APP_SECRET)
    # 示例:查询商品详情(替换为实际商品ID)
    product_id = "10050058089xxxx"
    try:
        # 1. 获取商品基础信息
        detail = client.get_product_detail(product_id, country="US", currency="USD")
        # 2. 获取价格信息
        price = client.get_product_price(product_id)
        # 3. 获取运费模板(从商品详情中提取template_id)
        template_id = detail["data"]["freight_template_id"]
        freight = client.get_freight_template(template_id, country="US")
        
        # 解析核心数据(映射为标准字段)
        result = {
            "platform_code": "ALIEXPRESS",
            "product_id": product_id,
            "product_name": detail["data"]["product_title"],
            "original_price": price["data"]["original_price"],
            "current_price": price["data"]["sale_price"],
            "currency": "USD",
            "shipping_fee": freight["data"]["default_freight"],
            "total_price": float(price["data"]["sale_price"]) + float(freight["data"]["default_freight"])
        }
        print(json.dumps(result, ensure_ascii=False, indent=2))
    except Exception as e:
        print(f"采集失败:{e}")
2.3 接口调用关键注意事项
  1. 多站点 / 多币种适配
    • 不同国家站点的价格、运费差异极大(如俄罗斯站定价用 RUB,运费含本地物流费),需通过country参数指定目标站点;
    • 币种转换:可对接第三方汇率接口(如 Open Exchange Rates),将 USD/EUR 等统一转换为 CNY,示例:

      python

      运行

      def convert_currency(amount, from_curr, to_curr="CNY"):
          # 对接汇率接口获取实时汇率(示例为固定汇率,需替换为真实接口)
          exchange_rates = {"USD": 7.2, "EUR": 7.8, "RUB": 0.07}
          return amount * exchange_rates[from_curr]
      
  2. 签名排错
    • 若返回 “签名无效”,检查:参数排序是否升序、value 是否 URL 编码、时间戳是否为毫秒级、AppSecret 是否正确;
  3. 频率控制
    • 新增 Redis 限流逻辑(参考京东 API 的限流代码),控制单接口 QPS≤5,避免触发平台限流(返回 429 错误)。
三、无接口权限时的合规爬虫采集(补充方案)

若暂未获取 API 权限,可通过爬虫采集速卖通商品页数据(需严格遵守 robots 协议,仅用于非商用监控):

3.1 核心爬虫代码(应对动态渲染)

python

运行

import requests
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
from fake_useragent import UserAgent

class AliExpressSpider:
    def __init__(self):
        self.ua = UserAgent()
        # 配置ChromeOptions(反爬)
        self.options = webdriver.ChromeOptions()
        self.options.add_argument(f"user-agent={self.ua.random}")
        self.options.add_argument("--headless")  # 无头模式
        self.options.add_experimental_option("excludeSwitches", ["enable-automation"])
        self.driver = webdriver.Chrome(options=self.options)
        self.driver.implicitly_wait(10)

    def get_product_data(self, product_url):
        """采集商品页数据(示例:价格、名称、运费)"""
        try:
            self.driver.get(product_url)
            # 等待价格元素加载(应对JS动态渲染)
            price_elem = WebDriverWait(self.driver, 15).until(
                EC.presence_of_element_located((By.CLASS_NAME, "product-price-value"))
            )
            # 提取数据
            product_name = self.driver.find_element(By.CLASS_NAME, "product-title-text").text.strip()
            current_price = price_elem.text.strip().replace("$", "")
            shipping_fee = self.driver.find_element(By.CLASS_NAME, "product-shipping-price").text.strip()
            
            return {
                "product_name": product_name,
                "current_price": current_price,
                "shipping_fee": shipping_fee,
                "url": product_url
            }
        except Exception as e:
            raise Exception(f"爬虫采集失败:{e}")
        finally:
            self.driver.quit()

# 调用示例
if __name__ == "__main__":
    spider = AliExpressSpider()
    product_url = "https://www.aliexpress.com/item/10050058089xxxx.html"
    print(spider.get_product_data(product_url))
3.2 爬虫反爬应对策略
  1. IP 代理轮换:使用跨境代理池(如 911S5、BrightData),避免单 IP 被封(速卖通对境外 IP 更宽松,境内 IP 易受限);
  2. 请求延迟:每次请求间隔 10-15 秒,避免高频;
  3. 绕过检测:禁用 Chrome 自动化标识(enable-automation),配合随机 User-Agent、Cookie 池。
四、数据采集合规与风险控制
  1. 合规底线
    • 仅采集公开商品数据,禁止爬取用户隐私、订单信息;
    • 数据仅用于自身价格监控,禁止倒卖、商用;
  2. 风险应对
    • API 权限被限:预留备用开发者账号,及时调整调用频率;
    • 爬虫被封:优先切换至 API 方案,或降低采集频率;
    • 数据延迟:速卖通 API 数据延迟约 5-10 分钟,爬虫数据为实时但稳定性低,建议两者结合校验。
五、总结

速卖通数据采集优先选择开放平台 API(稳定、合规、数据完整),爬虫仅作为临时补充方案;核心需解决多站点 / 多币种适配、签名认证、运费模板解析三大问题,同时严格控制调用频率,确保符合平台规则。若需对接速卖通订单、库存等更深层数据,可进一步申请高级接口权限,并完善数据加密、日志监控体系。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值