淘宝 item_review 接口深度分析及 Python 实现

淘宝的 item_review 接口是用于获取商品评论数据的核心接口,能够获取淘宝平台上指定商品的用户评价、评分、追评等详细信息。这些数据对于商品口碑分析、用户需求挖掘、竞品对比等场景具有重要价值,是电商数据分析中不可或缺的一环。

一、接口核心特性分析

  1. 接口功能与定位
  • 核心功能:获取淘宝商品的用户评论数据,包括评价内容、评分、评价时间、用户信息、晒图等

  • 数据维度

    • 基础评价:评价 ID、商品 ID、用户昵称、评价时间、评价内容
    • 评分数据:商品描述、服务态度、物流速度等维度评分
    • 多媒体内容:评价图片、视频
    • 追评信息:追加评价内容、追评时间
    • 有用数:其他用户认为该评价有帮助的次数
  • 应用场景

    • 商品口碑分析与舆情监控
    • 用户需求与痛点挖掘
    • 竞品评价对比分析
    • 评价内容情感倾向分析
    • 产品改进建议提取
  1. 认证机制

淘宝开放平台(TOP)采用 appkey + access_token 的认证方式:

  • 开发者在淘宝开放平台注册应用,获取 appkeyappsecret
  • 通过 appkeyappsecret 获取 access_token(有有效期)
  • 每次请求需在参数中携带 access_token 进行身份验证
  • 评论接口属于敏感数据接口,需要额外申请权限
  1. 核心参数与响应结构

请求参数

参数名 类型 是否必填 说明
item_id String 商品 ID
access_token String 访问令牌
page Integer 页码,默认 1
page_size Integer 每页条数,默认 20,最大 100
sort String 排序方式:newest(最新)、helpful(最有帮助)、bad(差评)
has_image Boolean 是否只看有图评价,默认 false

响应核心字段

  • 分页信息:总评论数、总页数、当前页码

  • 评价列表:每条评价包含

    • 评价基本信息:评价 ID、用户信息、评价时间
    • 评分信息:各维度评分
    • 评价内容:文本内容、标签
    • 多媒体:图片 URL 列表
    • 追评:内容与时间
    • 商家回复:内容与时间

二、Python 脚本实现

以下是调用淘宝 item_review 接口的完整 Python 实现,包含令牌获取、接口调用、数据解析及简单的情感分析功能: import requests import time import json import logging import re from typing import Dict, Optional, List, Tuple from requests.exceptions import RequestException from snownlp import SnowNLP # 用于情感分析,需安装:pip install snownlp

配置日志 logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s" )

class TaobaoItemReviewAPI: def init (self, appkey: str, appsecret: str): """ 初始化淘宝评论API客户端 :param appkey: 淘宝开放平台appkey :param appsecret: 淘宝开放平台appsecret """ self.appkey = appkey self.appsecret = appsecret self.base_url = "eco.taobao.com/router/rest" self.access_token = None self.token_expires_at = 0 # token过期时间戳 self.session = requests.Session() self.session.headers.update({ "Content-Type": "application/x-www-form-urlencoded", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" })

python 复制代码
def _get_access_token(self) -> Optional[str]:
    """获取访问令牌"""
    # 检查token是否有效
    if self.access_token and self.token_expires_at > time.time() + 60:
        return self.access_token
        
    logging.info("获取新的access_token")
    params = {
        "method": "taobao.oauth.token",
        "appkey": self.appkey,
        "appsecret": self.appsecret,
        "grant_type": "client_credentials",
        "format": "json"
    }
    
    try:
        response = self.session.get(self.base_url, params=params, timeout=10)
        response.raise_for_status()
        result = response.json()
        
        if "error_response" in result:
            logging.error(f"获取access_token失败: {result['error_response']['msg']} (错误码: {result['error_response']['code']})")
            return None
            
        self.access_token = result["access_token"]
        self.token_expires_at = time.time() + result.get("expires_in", 86400)  # 默认为24小时
        return self.access_token
            
    except RequestException as e:
        logging.error(f"获取access_token请求异常: {str(e)}")
        return None

def get_item_reviews(self, 
                    item_id: str, 
                    page: int = 1, 
                    page_size: int = 20,
                    sort: str = "newest",
                    has_image: bool = False) -> Optional[Dict]:
    """
    获取商品评论
    :param item_id: 商品ID
    :param page: 页码
    :param page_size: 每页条数
    :param sort: 排序方式
    :param has_image: 是否只看有图评价
    :return: 评论数据
    """
    # 验证参数
    valid_sorts = ["newest", "helpful", "bad"]
    if sort not in valid_sorts:
        logging.error(f"无效的排序方式: {sort},支持: {valid_sorts}")
        return None
        
    if page_size < 1 or page_size > 100:
        logging.error(f"每页条数必须在1-100之间,当前为: {page_size}")
        return None
        
    # 获取有效的access_token
    if not self._get_access_token():
        return None
        
    params = {
        "method": "taobao.item.review.get",
        "appkey": self.appkey,
        "access_token": self.access_token,
        "item_id": item_id,
        "page": page,
        "page_size": page_size,
        "sort": sort,
        "has_image": "true" if has_image else "false",
        "format": "json",
        "v": "2.0"
    }
    
    try:
        response = self.session.get(self.base_url, params=params, timeout=15)
        response.raise_for_status()
        result = response.json()
        
        if "error_response" in result:
            logging.error(f"获取评论失败: {result['error_response']['msg']} (错误码: {result['error_response']['code']})")
            return None
            
        review_response = result.get("item_review_get_response", {})
        reviews_data = review_response.get("reviews", {})
        
        if not reviews_data:
            logging.warning("未获取到评论数据")
            return None
            
        # 格式化评论数据
        return self._format_review_data(reviews_data)
        
    except RequestException as e:
        logging.error(f"获取评论请求异常: {str(e)}")
        return None
    except json.JSONDecodeError:
        logging.error(f"评论响应解析失败: {response.text[:200]}...")
        return None

def _format_review_data(self, review_data: Dict) -> Dict:
    """格式化评论数据"""
    # 分页信息
    pagination = {
        "total_reviews": int(review_data.get("total", 0)),
        "total_pages": (int(review_data.get("total", 0)) + int(review_data.get("page_size", 20)) - 1) // int(review_data.get("page_size", 20)),
        "current_page": int(review_data.get("page", 1)),
        "page_size": int(review_data.get("page_size", 20))
    }
    
    # 格式化评论列表
    reviews = []
    for review in review_data.get("review", []):
        # 处理评价内容(去除HTML标签)
        content = self._clean_text(review.get("content", ""))
        
        # 情感分析(0-1之间,越接近1越积极)
        sentiment_score = self._analyze_sentiment(content)
        sentiment = "positive" if sentiment_score > 0.6 else "negative" if sentiment_score < 0.4 else "neutral"
        
        # 处理评价图片
        images = []
        if review.get("images"):
            images = [img.get("url") for img in review.get("images", {}).get("image", []) if img.get("url")]
        
        # 处理追评
        append_comment = None
        if review.get("append_comment"):
            append_comment = {
                "content": self._clean_text(review["append_comment"].get("content", "")),
                "created": review["append_comment"].get("created")
            }
        
        # 处理商家回复
        reply = None
        if review.get("reply"):
            reply = {
                "content": self._clean_text(review["reply"].get("content", "")),
                "created": review["reply"].get("created")
            }
        
        reviews.append({
            "review_id": review.get("review_id"),
            "user": {
                "nick": review.get("nick"),
                "avatar": review.get("user_avatar")
            },
            "rating": {
                "total": int(review.get("rating", 0)),  # 总评分
                "description": int(review.get("description_rating", 0)),  # 描述相符
                "service": int(review.get("service_rating", 0)),  # 服务态度
                "delivery": int(review.get("delivery_rating", 0))  # 物流速度
            },
            "content": content,
            "created_time": review.get("created"),
            "images": images,
            "append_comment": append_comment,
            "reply": reply,
            "useful": int(review.get("useful", 0)),  # 有用数
            "tags": review.get("tags", "").split(","),  # 评价标签
            "sentiment": {
                "score": round(sentiment_score, 4),
                "label": sentiment
            }
        })
    
    return {
        "pagination": pagination,
        "reviews": reviews,
        "raw_data": review_data  # 保留原始数据
    }

def _clean_text(self, text: str) -> str:
    """清理文本,去除HTML标签和特殊字符"""
    if not text:
        return ""
    # 去除HTML标签
    clean = re.sub(r'<.*?>', '', text)
    # 去除多余空格和换行
    clean = re.sub(r'\s+', ' ', clean).strip()
    return clean

def _analyze_sentiment(self, text: str) -> float:
    """使用SnowNLP进行情感分析"""
    if not text:
        return 0.5  # 中性
    try:
        return SnowNLP(text).sentiments
    except:
        return 0.5  # 分析失败时返回中性

def get_all_reviews(self, item_id: str, max_pages: int = 10, has_image: bool = False) -> List[Dict]:
    """
    获取多页评论数据
    :param item_id: 商品ID
    :param max_pages: 最大页数限制
    :param has_image: 是否只看有图评价
    :return: 所有评论列表
    """
    all_reviews = []
    page = 1
    
    while page <= max_pages:
        logging.info(f"获取第 {page} 页评论")
        result = self.get_item_reviews(
            item_id=item_id,
            page=page,
            page_size=100,  # 使用最大页大小减少请求次数
            has_image=has_image
        )
        
        if not result or not result["reviews"]:
            break
            
        all_reviews.extend(result["reviews"])
        
        # 检查是否已到最后一页
        if page >= result["pagination"]["total_pages"]:
            break
            
        page += 1
        # 控制请求频率,淘宝API有严格的QPS限制
        time.sleep(2)
        
    return all_reviews

def analyze_reviews(self, reviews: List[Dict]) -> Dict:
    """分析评论数据,生成统计报告"""
    if not reviews:
        return {}
        
    total = len(reviews)
    sentiment_counts = {"positive": 0, "neutral": 0, "negative": 0}
    rating_stats = {
        "total": [],
        "description": [],
        "service": [],
        "delivery": []
    }
    tag_counts = {}
    has_image_count = 0
    
    # 统计基础数据
    for review in reviews:
        # 情感统计
        sentiment = review["sentiment"]["label"]
        sentiment_counts[sentiment] += 1
        
        # 评分统计
        for key in rating_stats:
            if key in review["rating"]:
                rating_stats[key].append(review["rating"][key])
        
        # 标签统计
        for tag in review["tags"]:
            if tag:
                tag_counts[tag] = tag_counts.get(tag, 0) + 1
        
        # 有图评价统计
        if review["images"]:
            has_image_count += 1
    
    # 计算平均评分
    avg_ratings = {}
    for key, values in rating_stats.items():
        if values:
            avg_ratings[key] = round(sum(values) / len(values), 1)
        else:
            avg_ratings[key] = 0
    
    # 获取热门标签(前10)
    top_tags = sorted(tag_counts.items(), key=lambda x: x[1], reverse=True)[:10]
    
    return {
        "total_reviews": total,
        "sentiment_distribution": {
            "count": sentiment_counts,
            "percentage": {
                k: round(v / total * 100, 1) for k, v in sentiment_counts.items()
            }
        },
        "average_rating": avg_ratings,
        "image_review_ratio": round(has_image_count / total * 100, 1) if total > 0 else 0,
        "top_tags": top_tags
    }

示例调用 if name == "main": # 替换为实际的appkey和appsecret(从淘宝开放平台获取) APPKEY = "your_appkey" APPSECRET = "your_appsecret" # 替换为目标商品ID ITEM_ID = "123456789"

python 复制代码
# 初始化API客户端
api = TaobaoItemReviewAPI(APPKEY, APPSECRET)

# 方式1:获取单页评论
# review_result = api.get_item_reviews(
#     item_id=ITEM_ID,
#     page=1,
#     page_size=20,
#     sort="newest",
#     has_image=False
# )

# 方式2:获取多页评论
review_result = api.get_all_reviews(
    item_id=ITEM_ID,
    max_pages=3,
    has_image=False
)

if isinstance(review_result, dict) and "reviews" in review_result:
    print(f"共获取到 {review_result['pagination']['total_reviews']} 条评论")
    print(f"当前第 {review_result['pagination']['current_page']}/{review_result['pagination']['total_pages']} 页\n")
    
    # 打印前3条评论
    for i, review in enumerate(review_result["reviews"][:3], 1):
        print(f"{i}. 用户: {review['user']['nick']}")
        print(f"   评分: {review['rating']['total']}分 (描述: {review['rating']['description']}, 服务: {review['rating']['service']}, 物流: {review['rating']['delivery']})")
        print(f"   时间: {review['created_time']}")
        print(f"   内容: {review['content'][:100]}{'...' if len(review['content'])>100 else ''}")
        print(f"   情感: {review['sentiment']['label']} (得分: {review['sentiment']['score']})")
        print(f"   有用数: {review['useful']}")
        if review['images']:
            print(f"   图片数: {len(review['images'])}")
        if review['append_comment']:
            print(f"   追评: {review['append_comment']['content'][:50]}{'...' if len(review['append_comment']['content'])>50 else ''}")
        print("-" * 100)
        
    # 分析评论
    analysis = api.analyze_reviews(review_result["reviews"])
    print("\n=== 评论分析报告 ===")
    print(f"总评论数: {analysis['total_reviews']}")
    print(f"情感分布: 正面 {analysis['sentiment_distribution']['percentage']['positive']}%, 中性 {analysis['sentiment_distribution']['percentage']['neutral']}%, 负面 {analysis['sentiment_distribution']['percentage']['negative']}%")
    print(f"平均评分: 总评分 {analysis['average_rating']['total']}, 描述相符 {analysis['average_rating']['description']}, 服务态度 {analysis['average_rating']['service']}, 物流速度 {analysis['average_rating']['delivery']}")
    print(f"有图评价占比: {analysis['image_review_ratio']}%")
    print("热门标签:")
    for tag, count in analysis['top_tags']:
        print(f"  {tag}: {count}次")
        
elif isinstance(review_result, list):
    # 处理多页评论结果
    print(f"共获取到 {len(review_result)} 条评论")
    
    # 分析评论
    analysis = api.analyze_reviews(review_result)
    print("\n=== 评论分析报告 ===")
    print(f"总评论数: {analysis['total_reviews']}")
    print(f"情感分布: 正面 {analysis['sentiment_distribution']['percentage']['positive']}%, 中性 {analysis['sentiment_distribution']['percentage']['neutral']}%, 负面 {analysis['sentiment_distribution']['percentage']['negative']}%")

三、 接口调用注意事项

  1. 调用限制与规范
  • QPS 限制:淘宝开放平台对评论接口有严格的 QPS 限制,通常为 1-5 次 / 秒
  • 数据权限:评论接口需要单独申请权限,个人开发者可能无法获取
  • 分页限制:多数商品只能获取前 100 页评论(约 1-2 万条)
  • 合规使用:评论数据受用户隐私保护,不得泄露用户个人信息
  • 调用频率:批量获取时建议设置 2-3 秒间隔,避免触发反爬机制
  1. 常见错误及解决方案
错误码 说明 解决方案
401 未授权或 token 无效 重新获取 access_token,检查权限是否足够
403 权限不足 申请评论接口访问权限,确认应用已通过审核
429 调用频率超限 降低调用频率,实现请求限流
110 商品 ID 无效 确认 item_id 是否正确,商品是否存在
27 API 不存在 检查接口名称是否正确,使用最新的 API 版本
500 服务器错误 实现重试机制,最多 3 次,间隔指数退避
  1. 数据解析要点
  • 文本清洗:评价内容可能包含 HTML 标签、表情符号等,需要预处理
  • 评分处理:淘宝评分通常为 1-5 分,需注意不同维度评分的映射关系
  • 时间格式:评价时间可能为时间戳或字符串,需统一转换为标准格式
  • 图片 URL:部分图片 URL 可能有时效性,需要及时保存或处理
  • 情感分析:中文评论情感分析需考虑语境和网络用语,可结合专业 NLP 工具

四、应用场景与扩展建议

典型应用场景

  • 商品口碑监控系统:实时监控商品评价变化,及时发现负面评价
  • 用户需求分析工具:从评论中提取用户对产品功能、特性的需求
  • 竞品评价对比平台:对比同类商品的评价数据,找出优势与不足
  • 客服辅助系统:自动识别需要回复的负面评价,提高客服效率
  • 产品改进建议提取:从评论中挖掘产品改进的具体建议

扩展建议

  • 实现评论关键词提取:使用 TF-IDF 或 TextRank 提取核心评价点
  • 构建情感趋势图:分析商品评论情感随时间的变化趋势
  • 开发负面评价预警:当负面评价比例超过阈值时触发警报
  • 结合销量数据:分析评价情感与销量变化的相关性
  • 实现多平台对比:整合淘宝、京东、拼多多等平台的评论数据进行综合分析
  • 开发可视化仪表板:直观展示评论分析结果,如情感分布饼图、标签云等

通过合理使用淘宝 item_review 接口,开发者可以构建全面的商品评价分析系统,为电商运营、产品改进和用户服务提供数据支持。使用时需严格遵守淘宝开放平台的使用规范和数据保护条款,确保合法合规地获取和使用评论数据

相关推荐
一点一木2 小时前
深度体验TRAE SOLO移动端7天:作为独立开发者,我把工作流揣进了兜里
前端·人工智能·trae
小郭的笔记1 天前
在 Trae SOLO 模型下,我是怎么用 JS + Python 啃下像素画解析算法的
trae
小怼子2 天前
TRAE 官方没有做的桌宠,我用 TRAE SOLO 给做出来了
trae
小雄Ya2 天前
构建AI导师,通勤路上偷偷学习惊艳所有人
agent·trae
飞哥数智坊2 天前
TRAE SOLO 三端接力,救了我一场分享会
人工智能·trae
鹏多多2 天前
Trae cn里使用Pencil来制作设计图的手把手教程
前端·ai编程·trae
FEF前端团队2 天前
AI 编程 Agent 全景解读:从 Chat 到 Agent,你的代码助手进化到了哪一步?
ai编程·cursor·trae
_風箏2 天前
TRAE SOLO 移动版的安装与测试
trae
Hector_zh3 天前
逐浪 · 第七篇:Trae-SOLO 多端协同 —— 从安装到完成任务的完整流程
人工智能·trae
流离岁月3 天前
trae运行java的main方法卡在加载插件进度条
ai·trae