Java爬虫淘宝拍立淘item_search_img拍接口示例代码

淘宝拍立淘(item_search_img)接口允许开发者上传一张商品图片,返回与之相似的商品列表,广泛用于比价、选品、竞品监控等场景。下面给出一份"纯 Java 版"爬取思路与示例代码,不依赖任何官方 SDK,也不带外链,方便快速集成到自有爬虫框架中。


一、核心流程

  1. 注册淘宝开放平台账号,创建应用,拿到 app_key / app_secret,并申请 taobao.item_search_img 权限。

  2. 把待搜索图片转成淘宝认可的"外部地址":

    • 方案 A:先调淘宝 pic/upload 接口拿到 imgId;

    • 方案 B:把图片直传 OSS/七牛等可公网访问的地址,复制 URL 即可。

  3. 按淘宝签名规范生成 sign(MD5,ASCII 升序 + app_secret 前后包夹)。

  4. 用 POST 方式提交到 eco.taobao.com/router/rest,Content-Type 为 application/x-www-form-urlencoded。

  5. 解析返回 JSON,提取 items→item 数组里的 title、price、pic_url、detail_url、sales 等字段。


二、关键参数

参数名 必填 说明
method 固定 taobao.item_search_img
app_key 应用唯一标识
timestamp 格式 yyyy-MM-dd HH:mm:ss
format json
v 2.0
sign_method md5
sign 按规范生成的签名
imgid 图片 URL(或 upload 后的 id)
cat 类目 ID,如 50010788 表示女装
page 页码,默认 1

三、Java 签名与请求示例

java 复制代码
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.*;
import org.json.JSONObject;

public class PailitaoCrawler {

    private static final String APP_KEY     = "your_app_key";
    private static final String APP_SECRET  = "your_app_secret";
    private static final String GATEWAY     = "https://eco.taobao.com/router/rest";

    public static void main(String[] args) throws Exception {
        String imgUrl = "https://your-domain.com/demo.jpg"; // 公网可访问
        String json   = searchByImage(imgUrl, 1);
        System.out.println(json);
    }

    public static String searchByImage(String imgUrl, int page) throws Exception {
        Map<String, String> params = new LinkedHashMap<>();
        params.put("method",       "taobao.item_search_img");
        params.put("app_key",      APP_KEY);
        params.put("timestamp",    new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        params.put("format",       "json");
        params.put("v",            "2.0");
        params.put("sign_method",  "md5");
        params.put("imgid",        imgUrl);
        params.put("page",         String.valueOf(page));

        String sign = generateSign(params, APP_SECRET);
        params.put("sign", sign);

        String body = buildQuery(params);
        return httpPost(GATEWAY, body);
    }

    private static String generateSign(Map<String, String> params, String secret) throws Exception {
        List<String> keys = new ArrayList<>(params.keySet());
        Collections.sort(keys);
        StringBuilder sb = new StringBuilder(secret);
        for (String k : keys) sb.append(k).append(params.get(k));
        sb.append(secret);
        byte[] bytes = MessageDigest.getInstance("MD5").digest(sb.toString().getBytes(StandardCharsets.UTF_8));
        StringBuilder hex = new StringBuilder();
        for (byte b : bytes) hex.append(String.format("%02X", b));
        return hex.toString();
    }

    private static String buildQuery(Map<String, String> params) throws Exception {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> e : params.entrySet()) {
            if (sb.length() > 0) sb.append('&');
            sb.append(e.getKey()).append('=')
              .append(URLEncoder.encode(e.getValue(), "UTF-8"));
        }
        return sb.toString();
    }

    private static String httpPost(String url, String body) throws Exception {
        java.net.HttpURLConnection conn = (java.net.HttpURLConnection) new java.net.URL(url).openConnection();
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        try (OutputStream os = conn.getOutputStream()) {
            os.write(body.getBytes(StandardCharsets.UTF_8));
        }
        try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
            StringBuilder res = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) res.append(line);
            return res.toString();
        }
    }
}

四、返回数据快速解析

返回片段示例(已格式化):

javascript 复制代码
{
  "item_search_img_response": {
    "items": {
      "item": [
        {
          "title": "日系宽松卫衣",
          "price": "89.00",
          "pic_url": "https://img.alicdn.com/xxx.jpg",
          "detail_url": "https://item.taobao.com/id=xxx",
          "sales": 1203
        }
      ]
    }
  }
}

用 org.json 或 fastjson 取出数组即可落地到数据库/ES。


五、常见踩坑

  1. sign 错误:确保 ASCII 升序、value 不编码、前后都带 secret。

  2. 图片地址防盗链:外部地址必须 200 且返回 image/*,否则淘宝会报 5001。

  3. 频率限制:默认 5000 次/日,超出会 403,需要缓存或队列削峰。

  4. 类目过滤:cat 传错会返回空列表,可先用 itemcats 接口拉全量映射表。

  5. 分页最多 100 页,每页 20 条,即 2000 条上限,深度翻页意义不大。

相关推荐
Boilermaker199211 小时前
[Java 并发编程] Synchronized 锁升级
java·开发语言
沈浩(种子思维作者)11 小时前
真的能精准医疗吗?癌症能提前发现吗?
人工智能·python·网络安全·健康医疗·量子计算
MM_MS11 小时前
Halcon变量控制类型、数据类型转换、字符串格式化、元组操作
开发语言·人工智能·深度学习·算法·目标检测·计算机视觉·视觉检测
꧁Q༒ོγ꧂12 小时前
LaTeX 语法入门指南
开发语言·latex
njsgcs12 小时前
ue python二次开发启动教程+ 导入fbx到指定文件夹
开发语言·python·unreal engine·ue
alonewolf_9912 小时前
JDK17新特性全面解析:从语法革新到模块化革命
java·开发语言·jvm·jdk
io_T_T12 小时前
迭代器 iteration、iter 与 多线程 concurrent 交叉实践(详细)
python
古城小栈12 小时前
Rust 迭代器产出的引用层数——分水岭
开发语言·rust
华研前沿标杆游学12 小时前
2026年走进洛阳格力工厂参观游学
python
Carl_奕然12 小时前
【数据挖掘】数据挖掘必会技能之:A/B测试
人工智能·python·数据挖掘·数据分析