在电商运营中,实时掌握商品动态(如价格波动、销量变化、库存状态等)对于商家决策至关重要。本文将通过实际代码演示,教你如何接入淘宝 API,搭建一个简单的淘宝商品实时数据监控系统。
一、准备工作
1. 开发环境
- 编程语言:Node.js(JavaScript)
- 所需库:axios(HTTP 请求)、express(Web 服务)、node-schedule(定时任务)
2. 淘宝开放平台准备
- 注册账号
- 获取 Api Key 和 Api Secret
- 申请商品数据相关 API 的调用权限(如 "商品详情查询"、"商品价格查询" 等)
二、API 接口分析
淘宝提供了丰富的 API 接口,我们主要关注以下几个:
- 商品详情接口:获取商品基本信息
- 商品价格接口:获取实时价格数据
- 商品销量接口:获取销售数据
接口调用需要遵循淘宝的规范,包括签名验证、参数传递等。
三、核心代码实现
1. 配置与工具函数
首先,我们需要创建配置文件和一些工具函数,处理 API 签名和请求:
javascript
const crypto = require('crypto');
const axios = require('axios');
// 配置信息
const config = {
apiKey: '你的ApiKey',
apiSecret: '你的ApiSecret',
apiUrl: 'https://eco.taobao.com/router/rest'
};
/**
* 生成API签名
* @param {Object} params 请求参数
* @returns {String} 签名结果
*/
function generateSign(params) {
// 1. 排序参数
const sortedParams = Object.keys(params).sort().reduce((obj, key) => {
obj[key] = params[key];
return obj;
}, {});
// 2. 拼接参数
let signStr = config.appSecret;
for (const key in sortedParams) {
signStr += `${key}${sortedParams[key]}`;
}
signStr += config.appSecret;
// 3. 计算MD5并转为大写
return crypto.createHash('md5').update(signStr).digest('hex').toUpperCase();
}
/**
* 调用淘宝API
* @param {String} method API方法名
* @param {Object} params 业务参数
* @returns {Promise} 接口返回结果
*/
async function callTaobaoApi(method, params = {}) {
try {
// 公共参数
const publicParams = {
app_key: config.appKey,
method,
format: 'json',
v: '2.0',
timestamp: new Date().toISOString().replace(/T/, ' ').replace(/..+/, ''),
sign_method: 'md5'
};
// 合并参数
const allParams = { ...publicParams, ...params };
// 生成签名
allParams.sign = generateSign(allParams);
// 发送请求
const response = await axios.get(config.apiUrl, { params: allParams });
return response.data;
} catch (error) {
console.error('API调用失败:', error);
throw error;
}
}
module.exports = {
callTaobaoApi
};
2. 商品数据监控核心逻辑
接下来实现商品监控的核心功能,包括获取商品数据、定时任务和数据存储:
javascript
const { callTaobaoApi } = require('./taobao-api-utils');
const schedule = require('node-schedule');
// 监控的商品ID列表
const monitorItemIds = ['123456', '789012']; // 替换为实际商品ID
// 存储监控数据
const monitorData = {};
/**
* 初始化监控数据存储
*/
function initMonitorData() {
monitorItemIds.forEach(itemId => {
monitorData[itemId] = {
basicInfo: null,
priceHistory: [],
salesHistory: []
};
});
}
/**
* 获取商品基本信息
* @param {String} itemId 商品ID
*/
async function getItemBasicInfo(itemId) {
try {
const result = await callTaobaoApi('taobao.item.get', {
fields: 'title,num,iid,detail_url,pic_url',
num_iid: itemId
});
if (result.error_response) {
console.error(`获取商品${itemId}基本信息失败:`, result.error_response);
return null;
}
return result.item_get_response.item;
} catch (error) {
console.error(`获取商品${itemId}基本信息出错:`, error);
return null;
}
}
/**
* 获取商品价格信息
* @param {String} itemId 商品ID
*/
async function getItemPrice(itemId) {
try {
const result = await callTaobaoApi('taobao.item.price.get', {
fields: 'price,cost_price,orginal_price',
num_iid: itemId
});
if (result.error_response) {
console.error(`获取商品${itemId}价格失败:`, result.error_response);
return null;
}
return {
...result.item_price_get_response.price,
timestamp: new Date()
};
} catch (error) {
console.error(`获取商品${itemId}价格出错:`, error);
return null;
}
}
/**
* 获取商品销售信息
* @param {String} itemId 商品ID
*/
async function getItemSales(itemId) {
try {
const result = await callTaobaoApi('taobao.item.sales.get', {
fields: 'sales,volume',
num_iid: itemId
});
if (result.error_response) {
console.error(`获取商品${itemId}销售信息失败:`, result.error_response);
return null;
}
return {
...result.item_sales_get_response.sales,
timestamp: new Date()
};
} catch (error) {
console.error(`获取商品${itemId}销售信息出错:`, error);
return null;
}
}
/**
* 执行一次监控任务
*/
async function runMonitorTask() {
console.log(`开始监控任务: ${new Date().toLocaleString()}`);
for (const itemId of monitorItemIds) {
// 如果没有基本信息,先获取一次
if (!monitorData[itemId].basicInfo) {
const basicInfo = await getItemBasicInfo(itemId);
if (basicInfo) {
monitorData[itemId].basicInfo = basicInfo;
console.log(`已获取商品基本信息: ${basicInfo.title}`);
}
}
// 获取价格信息
const priceInfo = await getItemPrice(itemId);
if (priceInfo) {
monitorData[itemId].priceHistory.push(priceInfo);
// 只保留最近100条记录
if (monitorData[itemId].priceHistory.length > 100) {
monitorData[itemId].priceHistory.shift();
}
console.log(`商品${itemId}价格: ${priceInfo.price}`);
}
// 获取销售信息
const salesInfo = await getItemSales(itemId);
if (salesInfo) {
monitorData[itemId].salesHistory.push(salesInfo);
// 只保留最近100条记录
if (monitorData[itemId].salesHistory.length > 100) {
monitorData[itemId].salesHistory.shift();
}
console.log(`商品${itemId}销量: ${salesInfo.sales}`);
}
// 检查价格是否有大幅变动
checkPriceChange(itemId);
}
console.log(`监控任务完成: ${new Date().toLocaleString()}`);
}
/**
* 检查价格是否有大幅变动
* @param {String} itemId 商品ID
*/
function checkPriceChange(itemId) {
const priceHistory = monitorData[itemId].priceHistory;
if (priceHistory.length < 2) return;
const lastPrice = parseFloat(priceHistory[priceHistory.length - 1].price);
const prevPrice = parseFloat(priceHistory[priceHistory.length - 2].price);
const changePercent = ((lastPrice - prevPrice) / prevPrice) * 100;
// 如果价格变动超过5%,发出警报
if (Math.abs(changePercent) > 5) {
const changeType = changePercent > 0 ? '上涨' : '下跌';
console.warn(`警告: 商品${itemId}价格${changeType}${Math.abs(changePercent).toFixed(2)}%!`);
// 这里可以添加发送邮件或短信通知的逻辑
}
}
/**
* 启动监控服务
*/
function startMonitor() {
initMonitorData();
// 立即执行一次
runMonitorTask();
// 定时任务,每10分钟执行一次
const job = schedule.scheduleJob('*/10 * * * *', runMonitorTask);
console.log('商品监控服务已启动,每10分钟更新一次数据');
return job;
}
// 启动监控
const monitorJob = startMonitor();
// 提供获取监控数据的接口
function getMonitorData() {
return monitorData;
}
module.exports = {
getMonitorData
};
3. 数据展示 Web 服务
最后,我们创建一个简单的 Web 服务,用于展示监控数据:
javascript
const express = require('express');
const app = express();
const { getMonitorData } = require('./taobao-monitor');
// 设置模板引擎
app.set('view engine', 'ejs');
// 静态文件目录
app.use(express.static('public'));
// 首页展示监控数据
app.get('/', (req, res) => {
const data = getMonitorData();
res.render('index', { monitorData: data });
});
// 提供API接口获取JSON数据
app.get('/api/monitor-data', (req, res) => {
res.json(getMonitorData());
});
// 启动服务器
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`监控展示服务已启动,访问 http://localhost:${port}`);
});
4. 前端页面
创建一个简单的前端页面,用于可视化展示监控数据:
ini
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>淘宝商品实时监控</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.8/dist/chart.umd.min.js"></script>
</head>
<body class="bg-gray-100">
<div class="container mx-auto px-4 py-8">
<header class="mb-8">
<h1 class="text-3xl font-bold text-gray-800 flex items-center">
<i class="fa fa-line-chart text-blue-500 mr-3"></i>
淘宝商品实时监控系统
</h1>
<p class="text-gray-600 mt-2">实时跟踪商品价格与销量变化</p>
</header>
<div id="monitor-container" class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- 商品监控卡片将通过JavaScript动态生成 -->
</div>
</div>
<script>
// 定时刷新数据
function refreshData() {
fetch('/api/monitor-data')
.then(response => response.json())
.then(data => renderMonitorData(data))
.catch(error => console.error('获取数据失败:', error));
}
// 渲染监控数据
function renderMonitorData(data) {
const container = document.getElementById('monitor-container');
container.innerHTML = '';
for (const itemId in data) {
const itemData = data[itemId];
if (!itemData.basicInfo) continue;
const card = document.createElement('div');
card.className = 'bg-white rounded-lg shadow-md overflow-hidden transition-transform hover:scale-[1.01]';
// 构建卡片内容
card.innerHTML = `
<div class="p-5">
<div class="flex justify-between items-start mb-4">
<div>
<h2 class="text-xl font-semibold text-gray-800">${itemData.basicInfo.title}</h2>
<p class="text-gray-500 text-sm mt-1">商品ID: ${itemId}</p>
</div>
<img src="${itemData.basicInfo.pic_url}" alt="${itemData.basicInfo.title}" class="w-20 h-20 object-cover rounded">
</div>
<div class="grid grid-cols-2 gap-4 mb-4">
<div class="bg-gray-50 p-3 rounded">
<p class="text-gray-500 text-sm">当前价格</p>
<p class="text-2xl font-bold text-red-500">
¥${itemData.priceHistory.length > 0 ? itemData.priceHistory[itemData.priceHistory.length - 1].price : 'N/A'}
</p>
</div>
<div class="bg-gray-50 p-3 rounded">
<p class="text-gray-500 text-sm">累计销量</p>
<p class="text-2xl font-bold text-blue-500">
${itemData.salesHistory.length > 0 ? itemData.salesHistory[itemData.salesHistory.length - 1].sales : 'N/A'}
</p>
</div>
</div>
<div>
<h3 class="text-sm font-medium text-gray-700 mb-2">价格趋势</h3>
<canvas class="price-chart" data-item-id="${itemId}" height="150"></canvas>
</div>
</div>
`;
container.appendChild(card);
}
// 绘制价格趋势图表
drawPriceCharts(data);
}
// 绘制价格趋势图表
function drawPriceCharts(data) {
document.querySelectorAll('.price-chart').forEach(canvas => {
const itemId = canvas.getAttribute('data-item-id');
const itemData = data[itemId];
if (!itemData || itemData.priceHistory.length < 2) return;
// 准备图表数据
const labels = itemData.priceHistory.map(entry => {
const date = new Date(entry.timestamp);
return `${date.getHours()}:${date.getMinutes()}`;
});
const prices = itemData.priceHistory.map(entry => parseFloat(entry.price));
// 绘制图表
new Chart(canvas, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: '价格 (¥)',
data: prices,
borderColor: '#ef4444',
backgroundColor: 'rgba(239, 68, 68, 0.1)',
tension: 0.3,
fill: true
}]
},
options: {
responsive: true,
plugins: {
legend: {
display: false
}
},
scales: {
y: {
beginAtZero: false,
ticks: {
callback: function(value) {
return '¥' + value;
}
}
}
}
}
});
});
}
// 初始化页面
refreshData();
// 每30秒刷新一次数据
setInterval(refreshData, 30000);
</script>
</body>
</html>
四、系统运行与扩展
1. 运行步骤
-
安装依赖:
npm install axios express node-schedule ejs
2.替换代码中的apiKey
和apiSecret
为你自己的密钥
3.替换monitorItemIds
为你要监控的商品 ID
4.启动程序:
node app.js
5.查看监控数据
2. 功能扩展建议
- 添加数据持久化存储(如使用 MySQL 或 MongoDB)
- 实现更复杂的报警机制(邮件、短信、企业微信通知等)
- 增加更多维度的数据分析(如价格对比、销售趋势预测)
- 支持批量导入商品 ID 进行监控
- 添加用户认证和权限管理
五、注意事项
- 淘宝 API 有调用频率限制,请勿设置过短的监控间隔
- 遵守淘宝的使用规范,不要将数据用于非法用途
- 生产环境中应加强错误处理和日志记录
- 考虑添加缓存机制,减少 API 调用次数
通过本文的演示,你已经了解了如何接入淘宝 API 并搭建一个简单的商品监控系统。在此基础上,你可以根据实际需求进行扩展和优化,构建更强大的电商数据分析工具。