Node.js/Python 调用 1688 API 实时拉取商品信息的实现方案

在电商业务中,实时获取商品信息是许多应用的核心需求。1688 作为国内知名的 B2B 电商平台,提供了丰富的 API 接口供开发者使用。本文将详细介绍如何使用 Node.js 和 Python 两种主流编程语言调用 1688 API,实现商品信息的实时拉取。

1688 API 调用准备工作

在开始编码前,需要完成以下准备工作:

  1. 注册获取 Api Key 和 Api Secret
  2. 了解 1688 API 的认证方式
  3. 熟悉需要调用的 API 接口文档(如商品详情查询接口)

Node.js 实现方案

Node.js 凭借其异步非阻塞特性,非常适合进行 API 调用等网络操作。以下是使用 Node.js 调用 1688 API 的实现:

复制代码
const axios = require('axios');
const crypto = require('crypto');
const querystring = require('querystring');

class Ali1688ApiClient {
  constructor(appKey, appSecret, accessToken = '') {
    this.appKey = appKey;
    this.appSecret = appSecret;
    this.accessToken = accessToken;
    this.apiUrl = 'https://gw.open.1688.com/openapi/param2/1/portals.open/';
  }

  /**
   * 生成签名
   * @param {Object} params 请求参数
   * @returns {string} 签名结果
   */
  generateSign(params) {
    // 按参数名ASCII码从小到大排序
    const sortedParams = Object.keys(params).sort().reduce((obj, key) => {
      obj[key] = params[key];
      return obj;
    }, {});

    // 拼接成"key=value"形式
    let signStr = this.appSecret;
    for (const key in sortedParams) {
      signStr += `${key}${sortedParams[key]}`;
    }
    signStr += this.appSecret;

    // SHA1加密并转为大写
    return crypto.createHash('sha1')
      .update(signStr, 'utf8')
      .digest('hex')
      .toUpperCase();
  }

  /**
   * 获取访问令牌
   * @param {string} code 授权码
   * @returns {Promise<Object>} 包含access_token的响应
   */
  async getAccessToken(code) {
    const params = {
      grant_type: 'authorization_code',
      client_id: this.appKey,
      client_secret: this.appSecret,
      code: code,
      redirect_uri: 'http://your-callback-url.com' // 需与应用配置一致
    };

    const response = await axios.post('https://gw.open.1688.com/openapi/oauth/token', 
      querystring.stringify(params), {
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded'
        }
      });

    if (response.data.access_token) {
      this.accessToken = response.data.access_token;
    }
    
    return response.data;
  }

  /**
   * 通用API请求方法
   * @param {string} apiName API名称
   * @param {Object} params API参数
   * @returns {Promise<Object>} API响应结果
   */
  async request(apiName, params = {}) {
    if (!this.accessToken) {
      throw new Error('Access token is not set. Please get access token first.');
    }

    // 公共参数
    const publicParams = {
      app_key: this.appKey,
      method: `portals.open.${apiName}`,
      access_token: this.accessToken,
      timestamp: new Date().toISOString().replace(/T/, ' ').replace(/\..+/, ''),
      format: 'json',
      v: '1.0',
      sign_method: 'sha1'
    };

    // 合并参数
    const requestParams = { ...publicParams, ...params };
    
    // 生成签名
    requestParams.sign = this.generateSign(requestParams);

    // 发送请求
    const response = await axios.get(this.apiUrl + apiName, { params: requestParams });
    return response.data;
  }

  /**
   * 获取商品详情
   * @param {string} offerId 商品ID
   * @returns {Promise<Object>} 商品详情
   */
  async getProductDetail(offerId) {
    return this.request('offer.get', {
      offerId: offerId,
      fields: 'offerId,title,picUrl,price,minAmount,detailUrl'
    });
  }

  /**
   * 搜索商品
   * @param {string} keyword 搜索关键词
   * @param {number} page 页码
   * @param {number} pageSize 每页数量
   * @returns {Promise<Object>} 搜索结果
   */
  async searchProducts(keyword, page = 1, pageSize = 20) {
    return this.request('offer.search', {
      keywords: keyword,
      pageNo: page,
      pageSize: pageSize,
      fields: 'offerId,title,picUrl,price,minAmount,detailUrl'
    });
  }
}

module.exports = Ali1688ApiClient;

Node.js 实现说明

上面的代码主要包含两部分:

  1. 1688ApiClient.js:封装了 1688 API 的调用逻辑,包括签名生成、令牌管理和具体的 API 调用方法。

  2. example.js:展示了如何使用封装好的客户端进行商品搜索和商品详情获取。

核心实现要点:

  • 遵循 1688 API 的签名规则,对请求参数进行排序和加密
  • 实现 OAuth2.0 认证流程获取访问令牌
  • 封装常用的商品查询接口,如搜索和详情获取
  • 处理 API 调用中的异常情况

Python 实现方案

Python 作为另一种广泛使用的编程语言,也非常适合实现 1688 API 的调用。以下是 Python 版本的实现:

复制代码
import requests
import hashlib
import time
import json
from urllib.parse import urlencode, quote_plus

class Ali1688ApiClient:
    def __init__(self, app_key, app_secret, access_token=''):
        self.app_key = app_key
        self.app_secret = app_secret
        self.access_token = access_token
        self.api_url = 'https://gw.open.1688.com/openapi/param2/1/portals.open/'
    
    def generate_sign(self, params):
        """生成签名"""
        # 按参数名ASCII码从小到大排序
        sorted_params = sorted(params.items(), key=lambda x: x[0])
        
        # 拼接签名字符串
        sign_str = self.app_secret
        for key, value in sorted_params:
            sign_str += f"{key}{value}"
        sign_str += self.app_secret
        
        # SHA1加密并转为大写
        sign = hashlib.sha1(sign_str.encode('utf-8')).hexdigest().upper()
        return sign
    
    def get_access_token(self, code):
        """获取访问令牌"""
        params = {
            'grant_type': 'authorization_code',
            'client_id': self.app_key,
            'client_secret': self.app_secret,
            'code': code,
            'redirect_uri': 'http://your-callback-url.com'  # 需与应用配置一致
        }
        
        response = requests.post(
            'https://gw.open.1688.com/openapi/oauth/token',
            data=params
        )
        
        result = response.json()
        if 'access_token' in result:
            self.access_token = result['access_token']
        
        return result
    
    def request(self, api_name, params=None):
        """通用API请求方法"""
        if not self.access_token:
            raise Exception('Access token is not set. Please get access token first.')
        
        if params is None:
            params = {}
        
        # 公共参数
        public_params = {
            'app_key': self.app_key,
            'method': f'portals.open.{api_name}',
            'access_token': self.access_token,
            'timestamp': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()),
            'format': 'json',
            'v': '1.0',
            'sign_method': 'sha1'
        }
        
        # 合并参数
        request_params = {**public_params,** params}
        
        # 生成签名
        request_params['sign'] = self.generate_sign(request_params)
        
        # 发送请求
        url = f"{self.api_url}{api_name}"
        response = requests.get(url, params=request_params)
        return response.json()
    
    def get_product_detail(self, offer_id):
        """获取商品详情"""
        return self.request('offer.get', {
            'offerId': offer_id,
            'fields': 'offerId,title,picUrl,price,minAmount,detailUrl'
        })
    
    def search_products(self, keyword, page=1, page_size=20):
        """搜索商品"""
        return self.request('offer.search', {
            'keywords': keyword,
            'pageNo': page,
            'pageSize': page_size,
            'fields': 'offerId,title,picUrl,price,minAmount,detailUrl'
        })

Python 实现说明

Python 版本的实现与 Node.js 版本类似,也分为客户端封装和使用示例两部分:

  1. ali1688_api_client.py:封装了 1688 API 的核心调用逻辑,包括签名生成、令牌管理等。

  2. example.py:展示了如何使用客户端进行商品信息的拉取。

Python 实现的核心要点:

  • 使用 requests 库处理 HTTP 请求
  • 实现与 Node.js 版本相同的签名算法
  • 提供简洁的 API 接口供业务逻辑调用
  • 处理可能的异常情况

实时拉取策略

为了实现商品信息的实时拉取,可以采用以下策略:

  1. 定时任务:使用定时任务(如 Node.js 的 node-schedule,Python 的 APScheduler)定期调用 API 获取最新商品信息。

  2. 增量更新:通过记录上次拉取时间,只获取更新时间在该时间之后的商品信息,减少 API 调用量。

  3. 缓存机制:将拉取到的商品信息缓存到 Redis 等缓存系统中,减轻 API 调用压力,提高响应速度。

  4. 并发控制:对于大量商品的拉取需求,实现并发控制,避免触发 API 调用频率限制。

注意事项

在实际使用过程中,需要注意以下几点:

  1. API 调用频率限制:1688 API 有调用频率限制,需合理控制调用频率。

  2. 错误处理:实现完善的错误处理机制,处理网络异常、API 返回错误等情况。

  3. 令牌过期处理:Access Token 有有效期,需实现自动刷新机制。

  4. 参数安全:妥善保管 Api Key 和 Api Secret,避免泄露。

  5. 数据解析:根据 API 返回的实际数据结构进行解析,注意字段可能的变化。

总结

本文介绍了使用 Node.js 和 Python 两种语言调用 1688 API 实时拉取商品信息的实现方案。通过封装 API 客户端,我们可以方便地在不同的项目中复用代码,实现商品搜索、详情获取等功能。

在实际应用中,还需要根据具体业务需求进行优化,如实现缓存策略、错误重试机制等,以确保系统的稳定性和高效性。同时,需密切关注 1688 API 文档的更新,及时调整实现以适应 API 的变化。

相关推荐
Dontla5 小时前
Yarn命令与npm命令的区别与联系(npm:Node.js的官方包管理工具;Yarn:Facebook开发的JavaScript包管理工具)
javascript·npm·node.js
多看书少吃饭5 小时前
vue3+TS 前端调用海康摄像头视频流,后端用 Node.js 做 RTSP 转 WebSocket-FLV 转发,并且前后端优化延迟方案
前端·websocket·node.js
EndingCoder5 小时前
Node.js 模块系统详解
javascript·node.js
EndingCoder5 小时前
安装Node.js与NPM包管理器
前端·npm·node.js
2301_818732065 小时前
创建vue3项目,npm install后,运行报错,已解决
前端·npm·node.js
GDAL6 小时前
pacote:Node.js 生态中的包获取工具
node.js
liangshanbo12156 小时前
Node.js 进程生命周期核心笔记
node.js
丿似锦7 小时前
使用NVM管理Node.js版本
node.js·nvm
liangshanbo12158 小时前
Node.js 性能优化:实用技巧与实战指南
性能优化·node.js