以下实战教程基于第三方 API 网关(如 onebound.cn)暴露的 1688 关键词搜索接口编写,不依赖官方 SDK,只需普通开发者账号即可调用。示例代码全部用 Java 17 + Maven 实现,可直接复制到 IDEA 跑通。
一、接口原理速览
-
第三方网关把 1688 的
item_search接口封装成 REST 风格,GET 请求,返回 JSON。 -
调用前需在第三方平台申请
key / secret(通常即时下发,无需企业资质)。 -
关键词、价格区间、排序、分页等参数全部放在 QueryString,无需 OAuth。
-
每次请求必须计算一次 MD5 签名,签名串为
key=value升序拼接后 + secret。
二、开发环境准备
-
JDK ≥ 8(教程基于 17)
-
Maven 3.8+
-
依赖坐标(pom.xml)
XML
<dependencies>
<!-- 发送请求 -->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.2.1</version>
</dependency>
<!-- 解析 JSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
<!-- 工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies>
三、核心代码
- 签名工具
java
public class SignUtil {
public static String md5Upper(String src) {
try {
byte[] bs = MessageDigest.getInstance("MD5").digest(src.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : bs) sb.append(String.format("%02X", b));
return sb.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static String buildSign(Map<String, String> params, String secret) {
// 升序排序
String base = params.entrySet().stream()
.filter(e -> e.getValue() != null && !e.getValue().isEmpty())
.sorted(Map.Entry.comparingByKey())
.map(e -> e.getKey() + e.getValue())
.collect(Collectors.joining()) + secret;
return md5Upper(base);
}
}
- 搜索服务
java
public class AlibabaSearchService {
private static final String GATEWAY = "https://api-gw.onebound.cn/1688/item_search/";
private final String key;
private final String secret;
private final CloseableHttpClient client;
public AlibabaSearchService(String key, String secret) {
this.key = key;
this.secret = secret;
this.client = HttpClients.createDefault();
}
public JsonNode search(String keyword, int page, int pageSize) throws IOException {
Map<String, String> params = new TreeMap<>();
params.put("key", key);
params.put("secret", secret);
params.put("q", keyword);
params.put("page", String.valueOf(page));
params.put("page_size", String.valueOf(pageSize));
params.put("sort", "default");
params.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
params.put("sign", SignUtil.buildSign(params, secret));
URIBuilder ub = new URIBuilder(GATEWAY);
params.forEach(ub::addParameter);
HttpGet get = new HttpGet(ub.toString());
get.addHeader("Accept-Encoding", "gzip");
try (CloseableHttpResponse resp = client.execute(get)) {
String json = EntityUtils.toString(resp.getEntity(), StandardCharsets.UTF_8);
return new ObjectMapper().readTree(json);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
public void close() throws IOException {
client.close();
}
}
- 运行入口(带分页拉取示例)
java
public class Boot {
public static void main(String[] args) throws Exception {
String key = "你的key";
String secret = "你的secret";
String word = "蓝牙耳机";
int maxPage = 5; // 只抓 5 页做演示
try (AlibabaSearchService api = new AlibabaSearchService(key, secret)) {
for (int i = 1; i <= maxPage; i++) {
JsonNode root = api.search(word, i, 40);
JsonNode items = root.path("items").path("item");
if (items.isEmpty()) break;
items.forEach(n -> {
String title = n.path("title").asText();
String price = n.path("price").asText();
String numIid= n.path("num_iid").asText();
System.out.printf("%s\t%s\t%s%n", numIid, price, title);
});
Thread.sleep(800); // 限速,避免 429
}
}
}
}
四、返回字段速查(常用)
| 字段名 | 含义 |
|---|---|
| num_iid | 商品数字 ID |
| title | 商品标题 |
| price | 单价(元) |
| pic_url | 主图 URL |
| detail_url | PC 端详情页 |
| sales | 30 天成交件数 |
| seller_nick | 店铺名称 |
五、防封 & 调优经验
-
单 IP 建议 ≤ 15 QPS,超过后网关会丢 429 。
-
生产环境务必使用代理池(青果云、携趣等),轮换出口 IP。
-
对同一关键词做增量更新时,用 Redis 记录
num_iid布隆过滤器去重,内存省 90 %。 -
第三方网关偶尔 502,做好指数退避重试(3 次即可)。
-
签名
timestamp与服务器时间差 ≤ 300 s,否则报 "sign invalid"。
六、一键抓全量并落库(扩展思路)
-
用 MyBatis-Plus 批量插入 MySQL,主键冲突时更新价格、销量。
-
每页 40 条,10 页就是 400 SKU,可放到 CompletableFuture 并行拉取,15 线程 3 s 结束。
-
定时任务:Docker + cron,每小时增量跑一次,飞书 WebHook 推送变更条数。
七、结语
以上代码全部基于第三方网关实测通过,改两行密钥就能跑。
如果想进一步抓详情页 SKU、阶梯价,再把 num_iid 传给同一网关的 item_get 接口即可,解析逻辑与本文完全一致,不再赘述。祝各位选品、监控、算法训练一路畅通,爆单不封 IP!
如遇任何疑问或有进一步的需求,请随时与我私信或者评论联系。