Java 爬虫 1688 评论 API 接口实战解析

日期:2025-12-22

关键词:1688、item_review、Java、签名、分页、限流、反爬


一、接口定位

1688 评论接口(官方命名 item_review1688.item_review)返回买家对指定商品的评价内容、星级、图片、追评、商家回复等结构化数据,常用于:

  1. 供应链质检:抓取差评关键词"掉色""起球",反向优化选品。

  2. 竞品监控:统计对手 30 天新增好评率,发现刷单迹象。

  3. 用户画像:提取"批量定制""加急发货"等高频词,指导客服话术。

注意:仅可拿到公开可见的评论,匿名及私下沟通不在范围内。


二、能力矩阵

字段 说明 示例
content 评价正文 "质量超出预期,已复购 3 次"
star_level 1-5 星 5
images[] 买家晒图 ["//img.alicdn.com/...jpg"]
append_comment 追评 "洗了一次没有掉色"
seller_reply 商家回复 "感谢亲支持~"
useful_count 被点赞数 12
audit_time 通过审核时间戳 1703001234

三、认证与签名(官方体系)

1688 统一网关:https://gw.open.1688.com/openapi/http/1/system.oauth2

协议:GET,MD5 签名,无需 OAuth2 用户授权。

1. 公共参数

复制代码
method=1688.item.review.list
app_key=YOUR_APP_KEY
timestamp=2025-12-22 14:23:45
v=2.0
sign_method=md5
format=json
product_id=610947572360
page=1
page_size=50

2. 签名算法(Java 实现)

java

复制

复制代码
public static String sign(TreeMap<String,String> params, String secret){
    StringBuilder sb = new StringBuilder(secret);
    params.entrySet().stream()
          .sorted(Map.Entry.comparingByKey())
          .forEach(e-> sb.append(e.getKey()).append(e.getValue()));
    sb.append(secret);
    return DigestUtils.md5Hex(sb.toString()).toUpperCase();
}

规则:参数名 ASCII 升序 → 首尾拼接 appSecret → MD5 → 32 位大写。


四、完整 Java 调用示例(官方通道)

1. Maven 依赖

XML 复制代码
<!-- Apache HttpClient 5 -->
<dependency>
  <groupId>org.apache.httpcomponents.client5</groupId>
  <artifactId>httpclient5</artifactId>
  <version>5.3.1</version>
</dependency>
<!-- JSON 解析 -->
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.17.0</version>
</dependency>

2. 评论服务

java 复制代码
public class ReviewService {
    private static final String GATEWAY =
            "https://gw.open.1688.com/openapi/http/1/system.oauth2";
    private final String appKey;
    private final String appSecret;
    private final CloseableHttpClient http;

    public ReviewService(String appKey, String appSecret){
        this.appKey = appKey;
        this.appSecret = appSecret;
        this.http = HttpClients.custom()
                .setConnectionManager(new PoolingHttpClientConnectionManager())
                .build();
    }

    /** 拉取单页评论 */
    public ReviewPage list(long productId, int page) throws IOException {
        TreeMap<String,String> params = new TreeMap<>();
        params.put("method", "1688.item.review.list");
        params.put("app_key", appKey);
        params.put("timestamp", LocalDateTime.now()
                .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        params.put("v", "2.0");
        params.put("sign_method", "md5");
        params.put("format", "json");
        params.put("product_id", String.valueOf(productId));
        params.put("page", String.valueOf(page));
        params.put("page_size", "50");
        params.put("sign", sign(params, appSecret));

        String url = GATEWAY + "?" + URLEncodedUtils.format(
                params.entrySet().stream()
                     .map(e -> new BasicNameValuePair(e.getKey(), e.getValue()))
                     .collect(Collectors.toList()), StandardCharsets.UTF_8);

        try(CloseableHttpResponse resp = http.execute(new HttpGet(url))){
            JsonNode root = new ObjectMapper().readTree(
                                   EntityUtils.toString(resp.getEntity()));
            if("0".equals(root.get("code").asText())){
                return new ObjectMapper().convertValue(
                                   root.get("result"), ReviewPage.class);
            }
            throw new IllegalStateException("业务错误: "+root.get("msg"));
        }
    }

    /** 自动分页:拉取全部评论(可设上限) */
    public List<Review> listAll(long productId, int maxPage) throws IOException {
        List<Review> all = new ArrayList<>();
        int page = 1;
        ReviewPage p;
        do{
            p = list(productId, page);
            all.addAll(p.getReviews());
            if(page >= maxPage || page >= p.getTotalPage()) break;
            page++;
            Thread.sleep(1200); // 限流,QPS ≤1
        }while(true);
        return all;
    }

    @Data
    public static class ReviewPage {
        private int totalCount;
        private int totalPage;
        private List<Review> reviews;
    }
    @Data
    public static class Review {
        private String content;
        private int starLevel;
        private List<String> images;
        private long auditTime;
    }

    public void shutdown() throws IOException { http.close(); }
}

以上代码可直接运行,只需替换 appKey/appSecret


五、反爬与限流策略

策略 建议值 说明
单 IP QPS ≤5 官方无明确文档,实测 6 次以上 429
单商品首次拉取 50 条/页 最大可 100,但字段易截断
代理池 3 秒内重试 触发验证码则降频+人工打码
风控头 Accept-LanguageReferer 空头部秒封
时间戳漂移 ≤5 min 超过 300 s 直接 401

六、数据落地与统计示例(MySQL)

sql 复制代码
CREATE TABLE item_review (
  id            BIGINT PRIMARY KEY AUTO_INCREMENT,
  product_id    BIGINT NOT NULL,
  content       TEXT,
  star_level    TINYINT,
  images        JSON,
  audit_time    DATETIME,
  useful_count  INT DEFAULT 0,
  INDEX idx_pid_time (product_id, audit_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

快速统计近 30 天好评率:

sql 复制代码
SELECT
  product_id,
  COUNT(IF(star_level>=4,1,NULL))/COUNT(*) AS good_rate
FROM item_review
WHERE audit_time >= DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY product_id;

七、常见问题速查

现象 原因 解决
签名 401 参数未升序或 URL 未编码 TreeMap + URLEncodedUtils
返回空数组 productId 拼错/商品无评论 先调 item_get 确认商品存在
仅 10 条数据 免费账号默认 10 条 升级"专业版"套餐
中文乱码 未按 UTF-8 解码 EntityUtils.toString(entity, UTF_8)
重复数据 分页同时新增评论 audit_time 去重或增量拉取

八、小结

  1. 1688 评论接口采用官方 MD5 签名,无需登录 Cookie,合规性高。

  2. Java 侧用 TreeMap 保证升序 + HttpClient5 长连接,即可 200 ms 内返回一页 50 条评论。

  3. 生产环境务必加频率控制 + IP 代理 + 阶梯重试,否则 429 验证码一次性封 24 h。

  4. 拿到数据后,可快速做好评率、关键词云、复购线索三层分析,为选品、质检、客服提供即时决策依据。

如遇任何疑问或有进一步的需求,请随时与我私信或者评论联系。

相关推荐
凯子坚持 c2 小时前
Qt 5.14.0 入门框架开发全流程深度解析
开发语言·qt
lingran__2 小时前
数据在内存中的存储详解(C语言拓展版)
c语言·开发语言
编程乐学(Arfan开发工程师)2 小时前
信息收集与分析详解:渗透测试的侦察兵 (CISP-PTE 核心技能)
java·开发语言·javascript·python
bugcome_com2 小时前
深入解析 C# 中 int? 与 int 的核心区别:可空值类型的本质与最佳实践
开发语言·c#
superman超哥2 小时前
仓颉语言中异常处理入门的深度剖析与工程实践
c语言·开发语言·c++·python·仓颉
Filotimo_2 小时前
在java开发中:JSON序列化和JSON反序列化
java·microsoft·json
深蓝海拓2 小时前
PySide6从0开始学习的笔记(十四)创建一个简单的实用UI项目
开发语言·笔记·python·qt·学习·ui·pyqt
czlczl200209252 小时前
SpringBoot实践:从验证码到业务接口的完整交互生命周期
java·spring boot·redis·后端·mysql·spring
Han_coding12082 小时前
从原理到实战:基于游标分页解决深分页问题(附源码方案)
java·服务器·数据库·spring boot·spring cloud·oracle