除了 Python,淘宝商品详情 API 接口采集还可通过Java、Go、Node.js、PHP等主流语言实现,核心逻辑均围绕「参数构造→签名生成→HTTP 请求→JSON 解析」,以下是各语言的完整实现方案,适配不同技术栈场景:
一、Java 实现方案(适配企业级开发)
1. 核心依赖(Maven)
xml
<!-- HTTP请求 -->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.3</version>
</dependency>
<!-- JSON解析 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.41</version>
</dependency>
<!-- 日期工具 -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.12.5</version>
</dependency>
2. 完整代码
java
运行
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import org.joda.time.DateTime;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
public class TaobaoItemDetailAPI {
// 配置项(替换为自己的)
private static final String APP_KEY = "你的App Key";
private static final String APP_SECRET = "你的App Secret";
private static final String API_URL = "https://eco.taobao.com/router/rest";
// 生成淘宝API签名
private static String generateSign(Map<String, String> params) throws NoSuchAlgorithmException {
// 1. 按参数名ASCII升序排序,过滤空值
List<Map.Entry<String, String>> sortedParams = new ArrayList<>(params.entrySet());
sortedParams.sort(Comparator.comparing(Map.Entry::getKey));
// 2. 拼接参数字符串
StringBuilder signStr = new StringBuilder();
for (Map.Entry<String, String> entry : sortedParams) {
if (entry.getValue() != null && !entry.getValue().isEmpty()) {
signStr.append(entry.getKey()).append(entry.getValue());
}
}
// 3. 首尾拼接App Secret,MD5加密转大写
signStr.insert(0, APP_SECRET).append(APP_SECRET);
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(signStr.toString().getBytes(StandardCharsets.UTF_8));
// 转16进制大写
StringBuilder md5Str = new StringBuilder();
for (byte b : digest) {
md5Str.append(String.format("%02X", b));
}
return md5Str.toString();
}
// 调用商品详情API
public static JSONObject getItemDetail(String numIid) throws Exception {
// 1. 构造请求参数
Map<String, String> params = new HashMap<>();
params.put("method", "taobao.item.get");
params.put("app_key", APP_KEY);
params.put("timestamp", new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
params.put("format", "json");
params.put("v", "2.0");
params.put("sign_method", "md5");
params.put("num_iid", numIid); // 商品ID
// 2. 生成签名
String sign = generateSign(params);
params.put("sign", sign);
// 3. 构造GET请求
List<BasicNameValuePair> paramList = new ArrayList<>();
for (Map.Entry<String, String> entry : params.entrySet()) {
paramList.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
// 4. 发起HTTP请求
try (CloseableHttpClient client = HttpClients.createDefault()) {
HttpGet httpGet = new HttpGet(API_URL + "?" + org.apache.hc.core5.http.NameValuePair.format(paramList, StandardCharsets.UTF_8));
try (CloseableHttpResponse response = client.execute(httpGet)) {
String responseStr = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
JSONObject result = JSON.parseObject(responseStr);
// 检查调用是否成功
if (result.getInteger("code") != 0) {
JSONObject error = result.getJSONObject("resp_data").getJSONObject("error_response");
throw new Exception("API调用失败:" + error.getString("msg") + "(错误码:" + error.getString("sub_code") + ")");
}
// 解析商品详情数据
return result.getJSONObject("resp_data").getJSONObject("item_get_response").getJSONObject("item");
} catch (ParseException | IOException e) {
throw new Exception("请求失败:" + e.getMessage());
}
}
}
// 主函数测试
public static void main(String[] args) {
try {
JSONObject itemDetail = getItemDetail("689712345678"); // 替换为目标商品ID
System.out.println("商品详情:" + itemDetail.toString(2));
} catch (Exception e) {
e.printStackTrace();
}
}
}
二、Go 实现方案(轻量高性能)
1. 核心依赖(无需额外安装,Go 内置库即可)
go
运行
// 仅需导入内置库
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"net/url"
"sort"
"strings"
"time"
)
2. 完整代码
go
运行
package main
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"net/url"
"sort"
"strings"
"time"
)
// 配置项
const (
appKey = "你的App Key"
appSecret = "你的App Secret"
apiURL = "https://eco.taobao.com/router/rest"
)
// 生成签名
func generateSign(params url.Values) string {
// 1. 按参数名ASCII升序排序
keys := make([]string, 0, len(params))
for k := range params {
keys = append(keys, k)
}
sort.Strings(keys)
// 2. 拼接参数字符串
var signStr strings.Builder
for _, k := range keys {
v := params.Get(k)
if v != "" {
signStr.WriteString(k)
signStr.WriteString(v)
}
}
// 3. 首尾拼接App Secret,MD5加密转大写
signStrStr := appSecret + signStr.String() + appSecret
md5Hash := md5.Sum([]byte(signStrStr))
sign := strings.ToUpper(hex.EncodeToString(md5Hash[:]))
return sign
}
// 调用商品详情API
func getItemDetail(numIid string) (map[string]interface{}, error) {
// 1. 构造参数
params := url.Values{}
params.Set("method", "taobao.item.get")
params.Set("app_key", appKey)
params.Set("timestamp", time.Now().Format("2006-01-02 15:04:05"))
params.Set("format", "json")
params.Set("v", "2.0")
params.Set("sign_method", "md5")
params.Set("num_iid", numIid)
// 2. 生成签名
sign := generateSign(params)
params.Set("sign", sign)
// 3. 发起请求
resp, err := http.Get(apiURL + "?" + params.Encode())
if err != nil {
return nil, fmt.Errorf("请求失败:%v", err)
}
defer resp.Body.Close()
// 4. 解析响应
var result map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, fmt.Errorf("解析JSON失败:%v", err)
}
// 检查调用状态
if code, ok := result["code"].(float64); ok && code != 0 {
errorResp := result["resp_data"].(map[string]interface{})["error_response"].(map[string]interface{})
return nil, fmt.Errorf("API调用失败:%s(错误码:%s)", errorResp["msg"], errorResp["sub_code"])
}
// 提取商品详情
item := result["resp_data"].(map[string]interface{})["item_get_response"].(map[string]interface{})["item"]
return item.(map[string]interface{}), nil
}
func main() {
// 调用示例
itemDetail, err := getItemDetail("689712345678")
if err != nil {
fmt.Println("采集失败:", err)
return
}
// 格式化输出
jsonStr, _ := json.MarshalIndent(itemDetail, "", " ")
fmt.Println("商品详情:", string(jsonStr))
}
三、Node.js 实现方案(前端 / 后端通用)
1. 核心依赖
bash
运行
npm install axios md5 # axios:HTTP请求,md5:签名加密
2. 完整代码
javascript
运行
const axios = require('axios');
const md5 = require('md5');
// 配置项
const APP_KEY = "你的App Key";
const APP_SECRET = "你的App Secret";
const API_URL = "https://eco.taobao.com/router/rest";
// 生成签名
function generateSign(params) {
// 1. 按参数名ASCII升序排序,过滤空值
const sortedKeys = Object.keys(params).filter(key => params[key] !== '' && params[key] !== undefined).sort();
// 2. 拼接参数字符串
let signStr = '';
sortedKeys.forEach(key => {
signStr += key + params[key];
});
// 3. 首尾拼接App Secret,MD5加密转大写
signStr = APP_SECRET + signStr + APP_SECRET;
return md5(signStr).toUpperCase();
}
// 调用商品详情API
async function getItemDetail(numIid) {
try {
// 1. 构造参数
const params = {
method: 'taobao.item.get',
app_key: APP_KEY,
timestamp: new Date().toLocaleString('zh-CN', {
year: 'numeric', month: '2-digit', day: '2-digit',
hour: '2-digit', minute: '2-digit', second: '2-digit',
hour12: false
}).replace(/\//g, '-').replace(/, /g, ' '),
format: 'json',
v: '2.0',
sign_method: 'md5',
num_iid: numIid
};
// 2. 生成签名
params.sign = generateSign(params);
// 3. 发起GET请求
const response = await axios.get(API_URL, { params });
const result = response.data;
// 检查调用状态
if (result.code !== 0) {
const error = result.resp_data.error_response;
throw new Error(`API调用失败:${error.msg}(错误码:${error.sub_code})`);
}
// 提取商品详情
return result.resp_data.item_get_response.item;
} catch (error) {
throw new Error(`采集失败:${error.message}`);
}
}
// 测试调用
getItemDetail('689712345678')
.then(itemDetail => {
console.log('商品详情:', JSON.stringify(itemDetail, null, 2));
})
.catch(err => {
console.error(err);
});
四、PHP 实现方案(适配电商网站后端)
1. 无需额外依赖(PHP 内置 curl 和 md5 函数)
2. 完整代码
php
运行
<?php
// 配置项
define('APP_KEY', '你的App Key');
define('APP_SECRET', '你的App Secret');
define('API_URL', 'https://eco.taobao.com/router/rest');
// 生成签名
function generateSign($params) {
// 1. 按参数名ASCII升序排序,过滤空值
ksort($params);
$signStr = '';
foreach ($params as $k => $v) {
if ($v !== '' && $v !== null) {
$signStr .= $k . $v;
}
}
// 2. 首尾拼接App Secret,MD5加密转大写
$signStr = APP_SECRET . $signStr . APP_SECRET;
return strtoupper(md5($signStr));
}
// 调用商品详情API
function getItemDetail($numIid) {
// 1. 构造参数
$params = [
'method' => 'taobao.item.get',
'app_key' => APP_KEY,
'timestamp' => date('Y-m-d H:i:s'),
'format' => 'json',
'v' => '2.0',
'sign_method' => 'md5',
'num_iid' => $numIid
];
// 2. 生成签名
$params['sign'] = generateSign($params);
// 3. 发起curl请求
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, API_URL . '?' . http_build_query($params));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$response = curl_exec($ch);
curl_close($ch);
if (!$response) {
throw new Exception('curl请求失败');
}
// 4. 解析JSON
$result = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception('JSON解析失败');
}
// 检查调用状态
if ($result['code'] !== 0) {
$error = $result['resp_data']['error_response'];
throw new Exception("API调用失败:{$error['msg']}(错误码:{$error['sub_code']})");
}
// 提取商品详情
return $result['resp_data']['item_get_response']['item'];
}
// 测试调用
try {
$itemDetail = getItemDetail('689712345678');
echo "商品详情:" . json_encode($itemDetail, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
} catch (Exception $e) {
echo "采集失败:" . $e->getMessage();
}
?>
五、各语言核心逻辑统一要点
- 签名生成:所有语言均需遵循「参数 ASCII 升序排序→过滤空值→首尾拼接 App Secret→MD5 加密转大写」,这是 API 调用成功的核心;
- 时间戳格式 :必须为
YYYY-MM-DD HH:mm:ss,且与服务器时间误差≤5 分钟; - 异常处理:需捕获网络超时、签名错误、权限错误等,针对性处理;
- 限流控制 :批量调用时需添加延迟(如
time.sleep(1)/Thread.sleep(1000)),适配淘宝 API 的 QPS 限制。
六、选型建议
- 企业级项目:优先选 Java(生态完善、稳定性高);
- 轻量高性能场景:选 Go(内存占用低、并发能力强);
- 前端 / 中小型后端:选 Node.js(开发效率高);
- PHP 电商网站:直接用 PHP 方案,无需额外适配。