日期:2025-12-22
关键词:1688、item_review、Java、签名、分页、限流、反爬
一、接口定位
1688 评论接口(官方命名 item_review 或 1688.item_review)返回买家对指定商品的评价内容、星级、图片、追评、商家回复等结构化数据,常用于:
-
供应链质检:抓取差评关键词"掉色""起球",反向优化选品。
-
竞品监控:统计对手 30 天新增好评率,发现刷单迹象。
-
用户画像:提取"批量定制""加急发货"等高频词,指导客服话术。
注意:仅可拿到公开可见的评论,匿名及私下沟通不在范围内。
二、能力矩阵
| 字段 | 说明 | 示例 |
|---|---|---|
| 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-Language、Referer |
空头部秒封 |
| 时间戳漂移 | ≤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 去重或增量拉取 |
八、小结
-
1688 评论接口采用官方 MD5 签名,无需登录 Cookie,合规性高。
-
Java 侧用
TreeMap保证升序 +HttpClient5长连接,即可 200 ms 内返回一页 50 条评论。 -
生产环境务必加频率控制 + IP 代理 + 阶梯重试,否则 429 验证码一次性封 24 h。
-
拿到数据后,可快速做好评率、关键词云、复购线索三层分析,为选品、质检、客服提供即时决策依据。
如遇任何疑问或有进一步的需求,请随时与我私信或者评论联系。