基于淘宝商品详情 API 的实时价格监控系统设计与实现

3 阅读9分钟

在电商消费场景中,商品价格的波动往往直接影响用户的购买决策。基于淘宝商品详情 API 构建实时价格监控系统,能够帮助用户自动跟踪商品价格变化、设置价格预警,实现智能化的购物决策辅助。本文将从系统设计思路、核心功能实现、代码编写等维度,完整阐述该监控系统的开发过程。

一、系统整体设计

1.1 设计目标

本系统核心目标为:

  • 支持批量添加淘宝商品链接,解析商品基础信息;
  • 定时调用淘宝商品详情 API,获取实时价格数据;
  • 存储价格历史数据,支持价格走势分析;
  • 实现价格阈值预警,当价格低于设定值时触发通知(如邮件、短信);
  • 提供简单的可视化界面,展示价格变化趋势。

1.2 系统架构

系统采用分层架构设计,分为 4 个核心模块:

用户交互层

业务逻辑层

数据访问层

通知服务层

淘宝API接口

数据库

graph TD
    A[用户交互层] --> B[业务逻辑层]
    B --> C[数据访问层]
    B --> D[通知服务层]
    C --> E[淘宝API接口]
    C --> F[数据库]

用户交互层

业务逻辑层

数据访问层

通知服务层

淘宝API接口

数据库

  • 用户交互层:提供商品添加、价格阈值设置、历史数据查看的界面;
  • 业务逻辑层:处理价格对比、定时任务、预警规则判断等核心逻辑;
  • 数据访问层:封装淘宝 API 调用、数据库增删改查操作;
  • 通知服务层:实现价格预警的消息推送功能。

1.3 技术选型

  • 开发语言:Python(简洁易上手,丰富的第三方库适配 API 调用、定时任务);
  • API 调用:淘宝开放平台 API(需申请开发者账号、获取 AppKey 和 AppSecret);
  • 数据库:SQLite(轻量级,无需额外部署,适合小型监控系统);
  • 定时任务:APScheduler(Python 主流定时任务框架);
  • 数据可视化:Matplotlib(价格走势图表生成);
  • 通知方式:SMTP(邮件通知)。

二、前置准备

2.1 淘宝开放平台配置

  1. 注册淘宝开放平台开发者账号;
  2. 获取ApiKeyApiSecret
  3. 申请商品详情 API(taobao.item_get)的调用权限;
  4. 熟悉 API 调用规则:请求格式、签名方式、调用频率限制。

2.2 环境依赖安装

执行以下命令安装所需 Python 库:

pip install requests apscheduler sqlite3 matplotlib python-dotenv

三、核心功能实现

3.1 数据库设计

创建 SQLite 数据库,包含goods(商品信息)和price_record(价格记录)两张表:

import sqlite3
from datetime import datetime

# 初始化数据库
def init_db():
    conn = sqlite3.connect('taobao_price_monitor.db')
    cursor = conn.cursor()
    
    # 商品表:存储商品ID、名称、链接、预警价格等
    cursor.execute('''
    CREATE TABLE IF NOT EXISTS goods (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        item_id TEXT UNIQUE NOT NULL,
        title TEXT,
        url TEXT,
        warn_price FLOAT,
        create_time DATETIME DEFAULT CURRENT_TIMESTAMP
    )
    ''')
    
    # 价格记录表:存储商品各时间点的价格
    cursor.execute('''
    CREATE TABLE IF NOT EXISTS price_record (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        item_id TEXT NOT NULL,
        price FLOAT NOT NULL,
        crawl_time DATETIME DEFAULT CURRENT_TIMESTAMP,
        FOREIGN KEY (item_id) REFERENCES goods (item_id)
    )
    ''')
    
    conn.commit()
    conn.close()

# 初始化数据库(首次运行执行)
init_db()

3.2 淘宝 API 调用封装

封装淘宝商品详情 API 的调用逻辑,处理签名、请求参数、响应解析:

import requests
import hashlib
import time
import json
from dotenv import load_dotenv
import os

# 加载环境变量(存储AppKey、AppSecret)
load_dotenv()
APP_KEY = os.getenv('TAOBAO_APP_KEY')
APP_SECRET = os.getenv('TAOBAO_APP_SECRET')

# 淘宝API签名生成函数
def generate_sign(params, app_secret):
    # 按参数名升序排序
    sorted_params = sorted(params.items(), key=lambda x: x[0])
    # 拼接参数字符串
    sign_str = app_secret + ''.join([f'{k}{v}' for k, v in sorted_params]) + app_secret
    # MD5加密并转大写
    sign = hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()
    return sign

# 调用淘宝商品详情API获取价格
def get_taobao_item_price(item_id):
    # API请求基础参数
    params = {
        'method': 'taobao.item_get',
        'app_key': APP_KEY,
        'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'),
        'format': 'json',
        'v': '2.0',
        'sign_method': 'md5',
        'item_id': item_id
    }
    
    # 生成签名
    params['sign'] = generate_sign(params, APP_SECRET)
    
    try:
        # 发送请求(淘宝API正式地址需替换)
        response = requests.get('https://eco.taobao.com/router/rest', params=params, timeout=10)
        result = json.loads(response.text)
        
        # 解析价格(需根据API实际返回格式调整)
        if 'item_get_response' in result and 'item' in result['item_get_response']:
            item = result['item_get_response']['item']
            price = float(item.get('price', 0))
            title = item.get('title', '')
            return {
                'item_id': item_id,
                'title': title,
                'price': price,
                'success': True
            }
        else:
            print(f"获取商品{item_id}信息失败:{result}")
            return {'success': False, 'error': 'API返回格式异常'}
    except Exception as e:
        print(f"调用API失败:{str(e)}")
        return {'success': False, 'error': str(e)}

3.3 价格监控核心逻辑

实现商品添加、价格爬取、历史数据存储、价格预警功能:

# 添加商品到监控列表
def add_goods(item_id, url, warn_price):
    # 先获取商品名称
    item_info = get_taobao_item_price(item_id)
    if not item_info['success']:
        return False, f"添加失败:{item_info['error']}"
    
    conn = sqlite3.connect('taobao_price_monitor.db')
    cursor = conn.cursor()
    try:
        cursor.execute('''
        INSERT OR IGNORE INTO goods (item_id, title, url, warn_price)
        VALUES (?, ?, ?, ?)
        ''', (item_id, item_info['title'], url, warn_price))
        conn.commit()
        return True, f"商品【{item_info['title']}】添加成功"
    except Exception as e:
        return False, f"添加失败:{str(e)}"
    finally:
        conn.close()

# 爬取单个商品价格并存储
def crawl_goods_price(item_id):
    item_info = get_taobao_item_price(item_id)
    if not item_info['success']:
        return False, item_info['error']
    
    conn = sqlite3.connect('taobao_price_monitor.db')
    cursor = conn.cursor()
    try:
        # 存储价格记录
        cursor.execute('''
        INSERT INTO price_record (item_id, price)
        VALUES (?, ?)
        ''', (item_id, item_info['price']))
        conn.commit()
        
        # 检查是否触发预警
        cursor.execute('SELECT warn_price FROM goods WHERE item_id = ?', (item_id,))
        warn_price = cursor.fetchone()[0]
        if item_info['price'] <= warn_price:
            send_warn_email(item_id, item_info['title'], item_info['price'], warn_price)
            return True, f"价格预警:商品{item_info['title']}当前价格{item_info['price']}≤预警价{warn_price}"
        return True, f"商品{item_info['title']}当前价格:{item_info['price']}"
    except Exception as e:
        return False, str(e)
    finally:
        conn.close()

# 批量爬取所有监控商品价格
def crawl_all_goods_price():
    conn = sqlite3.connect('taobao_price_monitor.db')
    cursor = conn.cursor()
    cursor.execute('SELECT item_id FROM goods')
    item_ids = [row[0] for row in cursor.fetchall()]
    conn.close()
    
    results = []
    for item_id in item_ids:
        success, msg = crawl_goods_price(item_id)
        results.append({'item_id': item_id, 'success': success, 'msg': msg})
    return results

# 邮件预警通知
def send_warn_email(item_id, title, current_price, warn_price):
    import smtplib
    from email.mime.text import MIMEText
    from email.header import Header
    
    # 配置邮箱信息(需替换为自己的邮箱参数)
    smtp_server = 'smtp.163.com'
    smtp_port = 25
    sender = 'your_email@163.com'
    password = 'your_email_password'
    receiver = 'target_email@qq.com'
    
    # 邮件内容
    subject = f"淘宝商品价格预警 - {title}"
    content = f"""
    <p>商品ID:{item_id}</p>
    <p>商品名称:{title}</p>
    <p>当前价格:{current_price} 元</p>
    <p>预警价格:{warn_price} 元</p>
    <p>当前价格已低于预警价,可考虑购买!</p>
    """
    
    msg = MIMEText(content, 'html', 'utf-8')
    msg['From'] = Header(sender, 'utf-8')
    msg['To'] = Header(receiver, 'utf-8')
    msg['Subject'] = Header(subject, 'utf-8')
    
    try:
        server = smtplib.SMTP(smtp_server, smtp_port)
        server.login(sender, password)
        server.sendmail(sender, receiver, msg.as_string())
        server.quit()
        print(f"预警邮件已发送至{receiver}")
    except Exception as e:
        print(f"发送预警邮件失败:{str(e)}")

3.4 定时任务配置

使用 APScheduler 实现定时价格爬取:

from apscheduler.schedulers.blocking import BlockingScheduler

# 启动定时监控任务
def start_monitor():
    scheduler = BlockingScheduler(timezone='Asia/Shanghai')
    # 每10分钟执行一次批量爬取(可根据API调用频率限制调整)
    scheduler.add_job(crawl_all_goods_price, 'interval', minutes=10, id='price_monitor_job')
    
    print("价格监控系统已启动,每10分钟执行一次价格爬取...")
    try:
        scheduler.start()
    except (KeyboardInterrupt, SystemExit):
        scheduler.shutdown()
        print("价格监控系统已停止")

# 价格走势可视化
def plot_price_trend(item_id):
    import matplotlib.pyplot as plt
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 解决中文显示问题
    plt.rcParams['axes.unicode_minus'] = False
    
    conn = sqlite3.connect('taobao_price_monitor.db')
    cursor = conn.cursor()
    # 查询商品名称和价格记录
    cursor.execute('SELECT title FROM goods WHERE item_id = ?', (item_id,))
    title = cursor.fetchone()[0]
    
    cursor.execute('''
    SELECT crawl_time, price FROM price_record 
    WHERE item_id = ? ORDER BY crawl_time
    ''', (item_id,))
    records = cursor.fetchall()
    conn.close()
    
    if not records:
        print("暂无价格记录")
        return
    
    # 提取时间和价格数据
    times = [record[0] for record in records]
    prices = [record[1] for record in records]
    
    # 绘制折线图
    plt.figure(figsize=(10, 6))
    plt.plot(times, prices, marker='o', linestyle='-', color='#ff4400')
    plt.title(f'商品【{title}】价格走势', fontsize=14)
    plt.xlabel('爬取时间', fontsize=12)
    plt.ylabel('价格(元)', fontsize=12)
    plt.xticks(rotation=45)
    plt.grid(True, alpha=0.3)
    plt.tight_layout()
    plt.savefig(f'{item_id}_price_trend.png')
    print(f"价格走势图表已保存为:{item_id}_price_trend.png")

3.5 系统入口

编写系统启动和基础操作的入口函数:

if __name__ == '__main__':
    # 示例:添加商品(替换为实际商品ID、链接、预警价格)
    # add_goods('123456789', 'https://item.taobao.com/item.htm?id=123456789', 99.0)
    
    # 示例:生成价格走势图表
    # plot_price_trend('123456789')
    
    # 启动定时监控
    start_monitor()

四、系统运行与测试

4.1 配置环境变量

创建.env文件,填入淘宝开放平台的密钥和邮箱信息:

TAOBAO_APP_KEY=你的淘宝AppKey
TAOBAO_APP_SECRET=你的淘宝AppSecret

4.2 运行流程

  1. 执行init_db()初始化数据库;
  2. 调用add_goods()添加需要监控的商品;
  3. 运行start_monitor()启动定时监控;
  4. 调用plot_price_trend()生成价格走势图表。

4.3 注意事项

  1. 淘宝 API 有调用频率限制,需根据平台规则调整定时任务间隔;
  2. 商品 ID 需从淘宝商品链接中提取(链接中id=后的数字);
  3. 邮箱通知需开启 SMTP 服务,并使用授权码而非登录密码;
  4. 实际生产环境中,建议将 SQLite 替换为 MySQL/PostgreSQL,提升并发和稳定性。

五、系统扩展方向

  1. 增加多平台支持:适配京东、拼多多等电商平台的 API;
  2. 优化通知方式:增加微信、短信等预警渠道;
  3. 前端界面开发:使用 Flask/Django 搭建 Web 界面,支持可视化操作;
  4. 数据分析功能:增加价格波动幅度计算、历史最低价对比等;
  5. 异常处理优化:增加 API 调用失败重试、网络异常自动恢复机制。

总结

  1. 淘宝商品价格监控系统核心由API 调用、定时任务、数据存储、预警通知四大模块构成,Python 的轻量化特性适配小型监控系统开发;
  2. 系统实现了商品添加、价格爬取、历史存储、预警推送、走势可视化等核心功能,可直接基于代码扩展适配个性化需求;
  3. 开发过程中需重点关注 API 调用规则(签名、频率)、数据解析准确性和预警通知的可靠性。

该系统不仅能满足个人用户的价格监控需求,也可通过扩展适配电商运营、比价平台等商业场景,具备较强的实用价值和扩展空间。