一、为什么要用 Java 而不是 Python?

维度JavaPython
反爬对抗多线程 + 动态代理池,易做成高并发GIL 限制,高并发需另起炉灶
工程化Maven/Gradle 一键依赖,CI/CD 成熟环境碎片化,服务器部署易踩坑
生态Jsoup、HtmlUnit、Selenium、WebMagic 任选Scrapy 一枝独秀,定制成本不低
企业合规大部分跨境电商公司后端就是 Java,直接复用同一套 DAO / Service需要额外微服务或消息队列对接

一句话:“Python 写原型快,Java 上生产稳。”
如果你做的只是毕业设计,请随意 Scrapy;如果你要每天 10 W 级 ASIN 长期稳定落地,Java 才是更省心的选择。


二、整体架构速览(5 分钟看懂)

┌-----------------------------┐
|  Amazon 商品详情页 HTML     |
└------------┬----------------┘
             │ 1. 随机 User-Agent + 代理池
             ▼
┌-----------------------------┐
|  解析层(Jsoup + CSS 选择器)|
|  异常重试 / 熔断 / 限流      |
└------------┬----------------┘
             │ 2. 清洗字段
             ▼
┌-----------------------------┐
|  仓库层(CSV/MySQL/Mongo)  |
|  每日增量 / 全量版本控制    |
└------------┬----------------┘
             │ 3. 报警&监控
             ▼
         Grafana + 钉钉群

三、开发前准备(3 件事)

  1. 环境
    JDK 17 + Maven 3.9 + IDEA 2024(示例基于 Maven,Gradle 同理)

  2. 依赖
    pom.xml 里一次性引入:

    xml
    <dependencies>
        <!-- 解析 HTML -->
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.17.2</version>
        </dependency>
        <!-- HTTP Client,带连接池 -->
        <dependency>
            <groupId>org.apache.httpcomponents.client5</groupId>
            <artifactId>httpclient5</artifactId>
            <version>5.3</version>
        </dependency>
        <!-- 简化 CSV 导出 -->
        <dependency>
            <groupId>com.opencsv</groupId>
            <artifactId>opencsv</artifactId>
            <version>5.8</version>
        </dependency>
        <!-- 日志 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.4.11</version>
        </dependency>
    </dependencies>
  3. 目标页面分析
    打开 Chrome → 访问任意 ASIN(如 https://www.amazon.com/dp/B08F7N8PDP)→ F12 → Elements
    把关键字段的 CSS 选择器先记在备忘录:

    字段选择器
    标题span#productTitle
    价格span.a-price.a-text-price.a-size-medium.apexPriceToPay .a-offscreen
    评分span.a-icon-alt(正则提取 “4.5 out”)
    评论数span#acrCustomerReviewText
    库存div#availability span
    图集script:contains(data) 里 JSON 解析
    五点div#feature-bullets ul li span

四、核心代码:最小可运行版本(MVP)

以下 120 行代码,一次性解决“请求 → 解析 → 落盘”黄金链路,复制即可跑通。

java

public class AmazonScraper {

    private static final Logger log = LoggerFactory.getLogger(AmazonScraper.class);

    // 1. 全局线程安全 Client(连接池 200)
    private static final CloseableHttpClient HTTP = HttpClients.custom()
            .setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " +
                          "(KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36")
            .setDefaultRequestConfig(RequestConfig.custom()
                    .setConnectTimeout(Timeout.ofSeconds(5))
                    .setResponseTimeout(Timeout.ofSeconds(8))
                    .build())
            .build();

    // 2. 字段 Bean
    @Data
    public static class Product {
        String asin;
        String title;
        String price;
        String rating;
        String reviewCount;
        String availability;
        String scrapeTime = LocalDateTime.now().toString();
    }

    // 3. 入口
    public static void main(String[] args) throws Exception {
        List<String> asins = List.of("B08F7N8PDP", "B08N5WRWNW", "B08N5M7S6K");
        List<Product> result = new ArrayList<>();

        for (String asin : asins) {
            try {
                Product p = scrape(asin);
                result.add(p);
                log.info("✅ 成功抓取 {}", asin);
                Thread.sleep(RandomUtils.nextInt(2, 4) * 1000L); // 友好限速
            } catch (Exception e) {
                log.error("❌ 抓取 {} 失败: {}", asin, e.getMessage());
            }
        }

        // 4. 落盘 CSV
        try (Writer w = Files.newBufferedWriter(Path.of("amazon.csv"));
             CSVWriter csv = new CSVWriter(w)) {
            StatefulBeanToCsv<Product> beanToCsv = new StatefulBeanToCsvBuilder<Product>(csv).build();
            beanToCsv.write(result);
        }
        log.info(">>> 共 {} 条数据已写入 amazon.csv", result.size());
    }

    // 5. 核心抓取逻辑
    private static Product scrape(String asin) throws IOException {
        String url = "https://www.amazon.com/dp/" + asin;
        ClassicHttpRequest req = ClassicRequestBuilder.get(url)
                .addHeader("Accept-Language", "en-US,en;q=0.9")
                .addHeader("Accept-Encoding", "gzip, deflate, br")
                .build();

        Document doc;
        try (ClassicHttpResponse resp = HTTP.execute(req)) {
            if (resp.getCode() != 200) throw new IOException("HTTP " + resp.getCode());
            doc = Jsoup.parse(EntityUtils.toString(resp.getEntity()));
        }

        Product p = new Product();
        p.setAsin(asin);
        p.setTitle(doc.select("span#productTitle").text().trim());
        p.setPrice(doc.select("span.a-price.a-text-price.apexPriceToPay .a-offscreen").text());
        p.setRating(doc.select("span.a-icon-alt").first().attr("content"));
        p.setReviewCount(doc.select("span#acrCustomerReviewText").text().replaceAll("[^0-9]", ""));
        p.setAvailability(doc.select("div#availability span").text());
        return p;
    }
}

运行日志示例:

22:33:12.121 ✅ 成功抓取 B08F7N8PDP
22:33:15.441 ✅ 成功抓取 B08N5WRWNW
22:33:18.752 ✅ 成功抓取 B08N5M7S6K
>>> 共 3 条数据已写入 amazon.csv

CSV 预览:

asintitlepriceratingreviewCountavailabilityscrapeTime
B08F7N8PDPApple AirPods Pro…$199.004.6184235In stock2025-10-21T22:33:12

五、反爬三板斧,让你的爬虫“长命百岁”

Amazon 的反爬策略 = “动态阈值 + 行为检测 + 验证码” 三维立体防御。
下面三板斧,亲测能把 429 概率降到 1% 以下:

  1. 代理池

    • 付费 residential 代理(如 BrightData、Oxylabs)(推荐)

    • 自建 Tor + 轻量池(适合预算有限,每日 <5k 请求)
      代码层只需把 HttpClient 包装成代理路由:

    java
    private static CloseableHttpClient buildProxyClient(String ip, int port){
        HttpHost proxy = new HttpHost(ip, port);
        return HttpClients.custom()
                .setProxy(proxy)
                .setUserAgent(...) // 随机 UA 池
                .build();
    }
  2. 请求特征 human-like

    • 每轮随机 sleep 2~5 s

    • 顺序打乱 ASIN 列表

    • 每天轮换 20+ UA + 不同 Accept-Language

    • 禁用 HttpClient 的 keep-alive(防止同一 TCP 被追踪)

  3. 熔断 & 重试

    • 返回 429/503 时指数退避:1s → 2s → 4s → 8s

    • 连续 5 次失败把代理扔进“冷宫” 10 分钟

    • 用 Netflix 的 Hystrix 或 Resilience4j 快速集成


六、把数据“喂”给业务:4 个真实场景

  1. 选品决策
    每天拉取竞品价格 + 评论增速,凌晨推送飞书群,运营同学起床即可看到“昨日降价 Top10”。

  2. 动态定价
    将抓取到的 FBA 价格、跟卖数丢进自研算法,自动调整 ERP 里的售价,保证“黄金购物车”胜率 ≥ 85%。

  3. 库存预警
    监控对手 availability 字段,一旦出现 “Only 1 left in stock” 就发邮件:可以加大广告抢流量了!

  4. 评论情感分析
    reviewText 一并收下来,用 HanLP 做中文分词、SnowNLP 做情感打分,找到 1~2 星差评集中关键词,反向优化自家产品说明书。


七、常见坑合集(血泪史)

现象解决
价格字段空页面是 JS 渲染,Jsoup 抓不到用 Selenium/HtmlUnit 先执行 JS,再拿最终 HTML
评分 null新上架商品无评论代码里判空,默认值 “N/A”
被重定向到验证码返回 200 但 title 是 “Robot Check”识别后自动暂停 30 min,切代理
图片 URL 失效Amazon 图片带时效参数及时把 https://images-na.ssl-images-amazon.com/… 转存到自家 OSS
CSV 中文乱码Excel 直接打开是 “???”写文件时指定 UTF-8 with BOM 或使用 OpenCSV 的 CSVWriter(writer, ',', '\uFEFF')

八、下一步:10 万级 ASIN 分布式方案

单线程玩 3 个 ASIN 没毛病,但老板一句“给我把全站耳机类目 30 万 SKU 每天扫一遍”怎么办?
把上面的 MVP 拆成“三件套”即可水平扩展:

  1. 调度层
    SpringBoot + Quartz,把 30 万 ASIN 按热度拆成 4 档,分别给 4 个 cron 表达式(小时级/日级/周级/月级)。

  2. 抓取节点
    Kubernetes 部署 10 个 Pod,每个 Pod 消费 RabbitMQ 的 ASIN 队列,抓取完回写结果到 MongoDB。

  3. 监控大盘
    Prometheus 采集“成功数 / 429 数 / 平均耗时”,Grafana 一屏展示;超过阈值自动钉钉 + 邮件。


九、写在最后的“防吃牢饭”提示

Amazon 的数据受《计算机欺诈与滥用法》(CFAA)及《数字千年版权法》(DMCA)保护,请务必

  1. 仅抓取“公开可见、无需登录” 的页面;

  2. 遵守 robots.txt(Amazon 几乎全站 allow:/,但频率需合理);

  3. 数据仅限内部商业分析,不得直接转载、转售或公开 API 化

  4. 生产环境先行法律评估,必要时与律师确认合规条款。

更多推荐