Java获取淘宝商品价格、图片与视频:淘宝开放平台API实战指南

1 阅读7分钟

一、接口概述

淘宝开放平台(Taobao Open Platform)提供了丰富的API接口,其中 taobao.item.get 是获取商品详情的核心接口。该接口允许开发者通过商品ID(num_iid)获取商品的完整信息,包括:

数据类型具体字段
基础信息标题、类目、品牌、店铺信息
价格体系商品价格、原价、促销价、库存
多媒体资源主图、详情图、SKU图片、视频链接
销售数据销量、评价数、收藏数
SKU信息规格组合、价格差异、库存分布

1.1 接口基本信息

  • 接口名称taobao.item.get(基础版)/ taobao.item.get_full(完整版)
  • 请求地址https://eco.taobao.com/router/rest
  • 请求方式:HTTP GET/POST
  • 返回格式:JSON
  • 协议版本:2.0

二、接入准备工作

2.1 注册开发者账号

完成以下步骤:

  1. 注册账号:使用企业支付宝实名认证
  2. 创建应用:进入"开发者中心" → "创建应用" → 选择"自用型"或"通用型"
  3. 申请权限:在"接口管理"中申请 taobao.item.get 权限

注意:基础版接口个人/企业均可免费申请,审核时效约1-2小时;完整版需企业资质

2.2 获取API凭证

创建应用后,在应用详情页获取:

String APP_KEY = "你的App Key";        // 应用标识
String APP_SECRET = "你的App Secret";  // 应用密钥,严禁泄露!

2.3 下载官方SDK(推荐)

淘宝官方提供Java SDK,封装了签名生成、请求发送等逻辑:

Maven依赖配置

xml

复制

<dependencies>
    <!-- 淘宝官方SDK -->
    <dependency>
        <groupId>com.taobao.api</groupId>
        <artifactId>taobao-sdk-java-auto</artifactId>
        <version>2024.11.28</version>
    </dependency>
    
    <!-- HTTP客户端 -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.14</version>
    </dependency>
    
    <!-- JSON解析 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>2.0.43</version>
    </dependency>
</dependencies>

三、核心实现:签名与请求

3.1 MD5签名算法

淘宝API采用MD5签名验证请求合法性,签名生成规则如下:

  1. 按参数名ASCII码升序排序所有参数
  2. 拼接为 key1=value1&key2=value2 格式(值需URL编码)
  3. 首尾拼接 App Secret
  4. MD5加密并转大写

Java实现代码

import org.apache.commons.codec.digest.DigestUtils;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

public class TaobaoApiSigner {
    
    /**
     * 生成淘宝API签名
     */
    public static String generateSign(Map<String, String> params, String appSecret) {
        try {
            // 1. 按参数名ASCII升序排序
            List<String> keys = new ArrayList<>(params.keySet());
            Collections.sort(keys);
            
            // 2. 拼接参数串
            StringBuilder paramStr = new StringBuilder();
            for (String key : keys) {
                String value = params.get(key);
                if (value != null && !value.isEmpty()) {
                    paramStr.append(key)
                           .append("=")
                           .append(URLEncoder.encode(value, StandardCharsets.UTF_8))
                           .append("&");
                }
            }
            
            // 移除最后一个&
            String queryString = paramStr.toString();
            if (queryString.endsWith("&")) {
                queryString = queryString.substring(0, queryString.length() - 1);
            }
            
            // 3. 首尾拼接App Secret
            String signStr = appSecret + queryString + appSecret;
            
            // 4. MD5加密并转大写
            return DigestUtils.md5Hex(signStr).toUpperCase();
            
        } catch (Exception e) {
            throw new RuntimeException("签名生成失败", e);
        }
    }
}

3.2 完整Java实现:获取商品详情

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class TaobaoItemApi {
    
    private static final String API_URL = "https://eco.taobao.com/router/rest";
    private static final String APP_KEY = "你的App Key";
    private static final String APP_SECRET = "你的App Secret";
    
    /**
     * 获取商品详情(含价格、图片、视频)
     * 
     * @param numIid 商品ID
     * @param fields 指定返回字段,null则返回全部
     * @return 商品详情JSON对象
     */
    public JSONObject getItemDetail(String numIid, String fields) {
        try {
            // 1. 构建公共参数
            Map<String, String> params = new HashMap<>();
            params.put("method", "taobao.item.get");
            params.put("app_key", APP_KEY);
            params.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            params.put("format", "json");
            params.put("v", "2.0");
            params.put("sign_method", "md5");
            params.put("num_iid", numIid);
            
            // 2. 指定返回字段(优化性能)
            if (fields == null) {
                // 默认获取关键字段:价格、图片、视频、SKU
                fields = "num_iid,title,price,original_price,pic_url,item_imgs," +
                        "desc,sku,props_name,property_alias,video," +
                        "num,detail_url,nick,sales";
            }
            params.put("fields", fields);
            
            // 3. 生成签名
            String sign = TaobaoApiSigner.generateSign(params, APP_SECRET);
            params.put("sign", sign);
            
            // 4. 发送HTTP POST请求
            return sendPostRequest(params);
            
        } catch (Exception e) {
            System.err.println("获取商品详情失败: " + e.getMessage());
            return null;
        }
    }
    
    /**
     * 发送HTTP POST请求
     */
    private JSONObject sendPostRequest(Map<String, String> params) throws IOException {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        
        try {
            HttpPost httpPost = new HttpPost(API_URL);
            
            // 构建表单参数
            StringBuilder formData = new StringBuilder();
            for (Map.Entry<String, String> entry : params.entrySet()) {
                formData.append(entry.getKey())
                       .append("=")
                       .append(entry.getValue())
                       .append("&");
            }
            
            StringEntity entity = new StringEntity(
                formData.toString(), 
                "application/x-www-form-urlencoded", 
                "UTF-8"
            );
            httpPost.setEntity(entity);
            
            // 执行请求
            HttpResponse response = httpClient.execute(httpPost);
            String result = EntityUtils.toString(response.getEntity(), "UTF-8");
            
            // 解析JSON
            return JSON.parseObject(result);
            
        } finally {
            httpClient.close();
        }
    }
    
    /**
     * 解析并打印商品关键信息
     */
    public void printProductInfo(JSONObject response) {
        if (response == null || !response.containsKey("item_get_response")) {
            System.out.println("未获取到有效数据");
            return;
        }
        
        JSONObject item = response.getJSONObject("item_get_response")
                                 .getJSONObject("item");
        
        System.out.println("========== 商品基本信息 ==========");
        System.out.println("商品ID: " + item.getString("num_iid"));
        System.out.println("商品标题: " + item.getString("title"));
        System.out.println("商品价格: ¥" + item.getString("price"));
        System.out.println("原价: ¥" + item.getString("original_price"));
        System.out.println("库存: " + item.getString("num"));
        System.out.println("销量: " + item.getString("sales"));
        
        // 主图信息
        System.out.println("\n========== 图片资源 ==========");
        System.out.println("主图URL: " + item.getString("pic_url"));
        
        // 详情图列表
        if (item.containsKey("item_imgs")) {
            JSONObject itemImgs = item.getJSONObject("item_imgs");
            if (itemImgs.containsKey("item_img")) {
                System.out.println("详情图数量: " + 
                    itemImgs.getJSONArray("item_img").size());
            }
        }
        
        // SKU信息
        if (item.containsKey("skus")) {
            JSONObject skus = item.getJSONObject("skus");
            System.out.println("\n========== SKU规格 ==========");
            System.out.println("SKU数量: " + 
                skus.getJSONArray("sku").size());
        }
        
        // 视频信息
        if (item.containsKey("video")) {
            JSONObject video = item.getJSONObject("video");
            System.out.println("\n========== 视频资源 ==========");
            System.out.println("视频URL: " + video.getString("url"));
            System.out.println("视频封面: " + video.getString("pic_url"));
        }
    }
    
    // 主程序入口
    public static void main(String[] args) {
        TaobaoItemApi api = new TaobaoItemApi();
        
        // 示例商品ID(替换为真实ID)
        String numIid = "520813250866";
        
        JSONObject result = api.getItemDetail(numIid, null);
        api.printProductInfo(result);
    }
}

四、返回数据结构解析

4.1 核心字段说明

字段名类型说明
num_iidLong商品数字ID
titleString商品标题
priceString当前售价
original_priceString原价
pic_urlString商品主图URL
item_imgsObject详情图数组
descString商品描述(HTML格式)
skusObjectSKU规格组合
videoObject主视频信息
numInteger库存数量
salesInteger销量

4.2 多媒体资源处理

图片下载示例

import java.io.*;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;

public class MediaDownloader {
    
    /**
     * 下载商品图片
     */
    public static void downloadImage(String imageUrl, String savePath) {
        try (InputStream in = new URL(imageUrl).openStream()) {
            Files.copy(in, Paths.get(savePath));
            System.out.println("图片下载成功: " + savePath);
        } catch (IOException e) {
            System.err.println("下载失败: " + e.getMessage());
        }
    }
    
    /**
     * 批量下载详情图
     */
    public static void downloadItemImages(JSONObject itemImgs, String folder) {
        if (!itemImgs.containsKey("item_img")) return;
        
        JSONArray images = itemImgs.getJSONArray("item_img");
        for (int i = 0; i < images.size(); i++) {
            JSONObject img = images.getJSONObject(i);
            String url = img.getString("url");
            String ext = url.substring(url.lastIndexOf("."));
            String filename = folder + "/detail_" + (i+1) + ext;
            
            downloadImage(url, filename);
            
            // 限速:避免触发反爬
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

视频处理说明: 淘宝商品视频通常返回的是播放地址或封面图URL,需使用第三方工具(如FFmpeg)进行下载转码。

五、使用官方SDK简化开发

淘宝官方Java SDK封装了签名和请求逻辑,使用更简洁:

import com.taobao.api.ApiException;
import com.taobao.api.DefaultTaobaoClient;
import com.taobao.api.TaobaoClient;
import com.taobao.api.request.ItemGetRequest;
import com.taobao.api.response.ItemGetResponse;

public class TaobaoSdkDemo {
    
    public static void main(String[] args) {
        // 初始化客户端
        String serverUrl = "https://eco.taobao.com/router/rest";
        String appKey = "你的App Key";
        String appSecret = "你的App Secret";
        
        TaobaoClient client = new DefaultTaobaoClient(serverUrl, appKey, appSecret);
        
        // 构建请求
        ItemGetRequest req = new ItemGetRequest();
        req.setNumIid(520813250866L);
        req.setFields("num_iid,title,price,pic_url,item_imgs,sku,video");
        
        try {
            ItemGetResponse rsp = client.execute(req);
            System.out.println(rsp.getBody());
            
            // 获取商品对象
            if (rsp.isSuccess()) {
                com.taobao.api.domain.Item item = rsp.getItem();
                System.out.println("标题: " + item.getTitle());
                System.out.println("价格: " + item.getPrice());
            }
            
        } catch (ApiException e) {
            e.printStackTrace();
        }
    }
}

六、实战注意事项

6.1 调用限制与优化

限制类型说明解决方案
频率限制免费版单日上限1000次 升级套餐或申请企业权限
并发限制默认QPS为10使用线程池控制并发
字段过滤使用fields参数减少数据传输只请求必要字段

6.2 数据安全规范

  1. 密钥保护APP_SECRET 禁止硬编码,使用环境变量或配置中心
  2. HTTPS传输:所有请求必须使用HTTPS
  3. 权限最小化:只申请必要的API权限

6.3 异常处理策略

public class ApiExceptionHandler {
    
    /**
     * 处理API返回错误
     */
    public static void handleError(JSONObject response) {
        if (!response.containsKey("error_response")) return;
        
        JSONObject error = response.getJSONObject("error_response");
        String code = error.getString("code");
        String msg = error.getString("msg");
        
        switch (code) {
            case "27": // 缺少必要参数
                System.err.println("参数错误: " + msg);
                break;
            case "25": // 签名错误
                System.err.println("签名验证失败,请检查App Secret");
                break;
            case "7": // 权限不足
                System.err.println("接口权限未开通或已过期");
                break;
            case "29": // 调用频率超限
                System.err.println("请求过于频繁,请稍后重试");
                try {
                    Thread.sleep(1000); // 休眠1秒后重试
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                break;
            default:
                System.err.println("API错误 [" + code + "]: " + msg);
        }
    }
}

七、相关接口推荐

接口名称功能使用场景
taobao.item.get_full获取完整商品信息需要详情页HTML、运费模板
taobao.item.sku.get获取SKU详细信息SKU价格库存精细化管理
taobao.tbk.item.get淘宝客商品查询推广商品搜索
taobao.tbk.item.convert链接转换生成推广链接

八、总结

本文详细介绍了使用Java调用淘宝开放平台API获取商品价格、图片和视频的技术方案。核心要点包括:

  1. 认证流程:注册开发者账号 → 创建应用 → 申请权限 → 获取凭证
  2. 签名机制:MD5加密,参数排序后首尾拼接App Secret
  3. 数据获取:使用 taobao.item.get 接口,通过 fields 参数指定返回内容
  4. 多媒体处理:图片直接下载,视频需额外处理
  5. 最佳实践:使用官方SDK、控制调用频率、做好异常处理

通过合理运用这些技术,开发者可以构建稳定的商品数据采集系统,应用于价格监控、竞品分析、智能选品等业务场景。