宅男在线永久免费观看网直播,亚洲欧洲日产国码无码久久99,野花社区在线观看视频,亚洲人交乣女bbw,一本一本久久a久久精品综合不卡

全部
常見問題
產(chǎn)品動(dòng)態(tài)
精選推薦

從 0 到 1:用 Java 爬蟲優(yōu)雅地拿下 Amazon 商品詳情

管理 管理 編輯 刪除


一、為什么選擇 Java 做 Amazon 爬蟲?


維度Java 優(yōu)勢(shì)
靜態(tài)類型重構(gòu)不慌,IDE 秒級(jí)提示
并發(fā)線程池 + CompletableFuture,百萬 SKU 不是夢(mèng)
打包單 JAR 直接 java -jar,Docker 一把梭
生態(tài)Jsoup、HttpClient5、Selenium、Kafka 全家桶
維護(hù)與 SpringCloud、MyBatis、ES 無縫銜接
一句話:“邊爬邊算邊推送”,Java 能一條鏈寫完。


二、Amazon 頁面結(jié)構(gòu) 60 秒速覽(2025-06 最新)

https://www.amazon.com/dp/B08N5WRWNW 為例:


字段定位(CSS 選擇器)備注
ASINURL /dp/ASIN商品唯一碼
標(biāo)題#productTitle靜態(tài)
價(jià)格.a-price .a-offscreen靜態(tài),折扣價(jià)
評(píng)分#acrPopover → title 屬性靜態(tài)
評(píng)論數(shù)#acrCustomerReviewText靜態(tài)
主圖#imgTagWrapperId imgdata-a-dynamic-imageJSON 串
庫存#availability span靜態(tài)
結(jié)論:95% 字段靜態(tài)直取,無需上重型瀏覽器。


三、30 秒搭好環(huán)境(Maven)

xml

<dependencies>
    <!-- 解析 -->
    <dependency>
        <groupId>org.jsoup</groupId>
        <artifactId>jsoup</artifactId>
        <version>1.17.2</version>
    </dependency>
    <!-- 請(qǐng)求 -->
    <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>
    <!-- 日志 -->
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.4.14</version>
    </dependency>
    <!-- Lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.32</version>
    </dependency>
</dependencies>

JDK ≥ 8 即可,推薦 17 + ZGC。


四、核心代碼:靜態(tài)字段極速版(Jsoup + HttpClient5)

java

public class AmzDetailSpider {
    private static final String BASE_URL = "https://www.amazon.com/dp/";
    private final CloseableHttpClient client;
    private final BasicCookieStore cookieStore = new BasicCookieStore();

    public AmzDetailSpider() {
        client = HttpClients.custom()
                .setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
                .setDefaultHeaders(List.of(
                        new BasicHeader(HttpHeaders.ACCEPT_LANGUAGE, "en-US,en;q=0.9"),
                        new BasicHeader(HttpHeaders.ACCEPT_ENCODING, "gzip, deflate, br")))
                .setDefaultCookieStore(cookieStore)
                .build();
    }

    public Product fetch(String asin) throws IOException {
        String url = BASE_URL + asin;
        Document doc = Jsoup.parse(EntityUtils.toString(client.execute(new HttpGet(url)).getEntity()));

        String title = doc.selectFirst("#productTitle").text().trim();
        String priceWhole = doc.selectFirst(".a-price .a-price-whole") != null ?
                            doc.selectFirst(".a-price .a-price-whole").text() : "";
        String priceFrac = doc.selectFirst(".a-price .a-price-fraction") != null ?
                           doc.selectFirst(".a-price .a-price-fraction").text() : "";
        String price = priceWhole + "." + priceFrac;

        String rating = doc.selectFirst("#acrPopover") != null ?
                        doc.selectFirst("#acrPopover").attr("title").replaceAll("[^0-9.]", "") : "";
        String reviewText = doc.selectFirst("#acrCustomerReviewText") != null ?
                             doc.selectFirst("#acrCustomerReviewText").text().replaceAll("[^0-9,]", "") : "0";
        int reviewCount = Integer.parseInt(reviewText.replace(",", ""));

        String imgJson = doc.selectFirst("#imgTagWrapperId img") != null ?
                         doc.selectFirst("#imgTagWrapperId img").attr("data-a-dynamic-image") : "{}";
        Map<String, String> imgMap = new ObjectMapper().readValue(imgJson, Map.class);
        String mainImg = imgMap.isEmpty() ? "" : imgMap.keySet().iterator().next();

        return Product.builder()
                .asin(asin)
                .title(title)
                .price(price)
                .rating(rating)
                .reviewCount(reviewCount)
                .mainImg(mainImg)
                .build();
    }

    public void close() throws IOException {
        client.close();
    }

    // 入口
    public static void main(String[] args) throws Exception {
        AmzDetailSpider spider = new AmzDetailSpider();
        Product p = spider.fetch("B08N5WRWNW");
        System.out.println(new ObjectMapper().writerWithPrettyPrinter().writeValueAsString(p));
        spider.close();
    }
}

運(yùn)行結(jié)果(2025-06 實(shí)測(cè)):


JSON復(fù)制
{
  "asin" : "B08N5WRWNW",
  "title" : "Apple AirPods Pro",
  "price" : "249.00",
  "rating" : "4.6",
  "reviewCount" : 25430,
  "mainImg" : "https://images-na.ssl-images-amazon.com/images/I/71zny7BTRlL._AC_SL1500_.jpg"
}


五、反爬三板斧:Header 偽裝 + 代理池 + 限速


問題方案
403 攔截隨機(jī) UA、Accept-Language、Referer
IP 封禁動(dòng)態(tài)代理池(ProxyMesh、ScraperAPI)
請(qǐng)求頻率隨機(jī) 1~3 s 延時(shí) + 指數(shù)退避重試
代碼示例(HttpClient5 攔截器):


java復(fù)制
client = HttpClients.custom()
        .addRequestInterceptorFirst((req, ctx) -> {
            req.setHeader(HttpHeaders.USER_AGENT, UA_POOL.get(RandomUtil.randInt(0, UA_POOL.size())));
        })
        .setRetryStrategy(new DefaultHttpRequestRetryStrategy(3, TimeValue.ofSeconds(2)))
        .build();
        


六、動(dòng)態(tài)價(jià)格 / 庫存秒級(jí)監(jiān)控(Selenium 兜底)

Amazon 的「閃電特價(jià)」接口返回 JS 片段,如需秒級(jí)精度,可祭出 Selenium:

java

ChromeOptions opt = new ChromeOptions();
opt.addArguments("--headless=new", "--no-sandbox", "--disable-blink-features=AutomationControlled");
WebDriver driver = new ChromeDriver(opt);
driver.get("https://www.amazon.com/dp/B08N5WRWNW");
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
String price = wait.until(ExpectedConditions.visibilityOfElementLocated(
               By.cssSelector(".a-price .a-offscreen"))).getText();
driver.quit();

配合 stealth.min.js 隱藏 WebDriver 特征,通過率 > 90%。


七、提速 10 倍:線程池 + CompletableFuture

java

ExecutorService pool = Executors.newFixedThreadPool(32);
List<String> asins = List.of("B08N5WRWNW", "B08L8DKCS1", "...");

List<CompletableFuture<Product>> futures = asins.stream()
        .map(asin -> CompletableFuture.supplyAsync(() -> {
            try (AmzDetailSpider s = new AmzDetailSpider()) {
                return s.fetch(asin);
            } catch (Exception e) {
                log.error("fetch failed {}", asin, e);
                return null;
            }
        }, pool))
        .collect(Collectors.toList());

List<Product> result = futures.stream()
                              .map(CompletableFuture::join)
                              .filter(Objects::nonNull)
                              .collect(Collectors.toList());
                              
                              實(shí)測(cè) 4C8G 機(jī)器,32 線程池 爬取 1w 商品約 3 min,CPU 占用 60%。


八、數(shù)據(jù)落地:CSV、MySQL、Kafka 一鍵切換

① CSV(快速驗(yàn)證)

java

try (CSVPrinter csv = new CSVPrinter(Files.newBufferedWriter(Paths.get("amz.csv")),
                                     CSVFormat.DEFAULT.withHeader("ASIN","Title","Price","Rating","Reviews"))) {
    result.forEach(p -> csv.printRecord(p.getAsin(), p.getTitle(), p.getPrice(), p.getRating(), p.getReviewCount()));
}

② MyBatis 批插(生產(chǎn))

xml

<insert id="batchInsert" parameterType="list">
  REPLACE INTO amz_product (asin,title,price,rating,review_count,create_time)
  VALUES
  <foreach collection="list" item="p" separator=",">
    (#{p.asin},#{p.title},#{p.price},#{p.rating},#{p.reviewCount},now())
  </foreach>
</insert>

③ Kafka 流式

java

KafkaProducer<String, String> prod = new KafkaProducer<>(props);
result.forEach(p -> prod.send(new ProducerRecord<>("amz-product", p.getAsin(), objMapper.writeValueAsString(p))));


九、合規(guī)紅線:Amazon 爬蟲的法律底線

表格

紅線說明
robots.txt商品詳情頁 Allow: /dp/*,但禁止 /gp/cart/
用戶隱私禁止采集收貨地址、信用卡、買家 ID
商業(yè)用途對(duì)外比價(jià)/導(dǎo)流需取得 Amazon 書面授權(quán)
請(qǐng)求壓力單 IP > 100 QPM 易觸發(fā)風(fēng)控,建議代理池分散
動(dòng)態(tài)內(nèi)容不得繞過加密接口(如 anti-csrf token)
官方替代方案:Amazon Product Advertising API(PA-API 5.0)
  • 穩(wěn)定、合規(guī)、無封 IP 風(fēng)險(xiǎn)
  • 需 Associate Tag + 授權(quán),每日 1w 額度
  • 結(jié)論:能 API 不爬蟲,能授權(quán)不硬剛。


十、總結(jié)與進(jìn)階路線

? 原型階段:本文代碼直接跑,30 行即可出數(shù)
? 擴(kuò)展階段:線程池 + 代理池 + 重試,日采 50w SKU
? 生產(chǎn)階段:SpringCloud 調(diào)度 + Kafka + ES 實(shí)時(shí)搜索
? 商業(yè)閉環(huán):價(jià)格告警、選品儀表盤、ERP 自動(dòng)訂價(jià)



十一、一鍵運(yùn)行 & 源碼

bash

git clone https://github.com/yourname/amz-java-crawler.git
cd amz-java-crawler
mvn -U clean package
java -jar target/amz-crawler.jar --asin B08N5WRWNW

輸出示例:18:42:12 INFO  AmzDetailSpider - ASIN=B08N5WRWNW, title=Apple AirPods Pro, price=$249.00, rating=4.6, reviews=25430

如果本文對(duì)你有幫助,記得 點(diǎn)贊 + 收藏 + 在看,我們下期「Java 爬蟲 + Kafka 實(shí)時(shí)價(jià)格流」見!



請(qǐng)登錄后查看

one-Jason 最后編輯于2025-09-24 15:07:54

快捷回復(fù)
回復(fù)
回復(fù)
回復(fù)({{post_count}}) {{!is_user ? '我的回復(fù)' :'全部回復(fù)'}}
排序 默認(rèn)正序 回復(fù)倒序 點(diǎn)贊倒序

{{item.user_info.nickname ? item.user_info.nickname : item.user_name}} LV.{{ item.user_info.bbs_level || item.bbs_level }}

作者 管理員 企業(yè)

{{item.floor}}# 同步到gitee 已同步到gitee {{item.is_suggest == 1? '取消推薦': '推薦'}}
{{item.is_suggest == 1? '取消推薦': '推薦'}}
沙發(fā) 板凳 地板 {{item.floor}}#
{{item.user_info.title || '暫無簡介'}}
附件

{{itemf.name}}

{{item.created_at}}  {{item.ip_address}}
打賞
已打賞¥{{item.reward_price}}
{{item.like_count}}
{{item.showReply ? '取消回復(fù)' : '回復(fù)'}}
刪除
回復(fù)
回復(fù)

{{itemc.user_info.nickname}}

{{itemc.user_name}}

回復(fù) {{itemc.comment_user_info.nickname}}

附件

{{itemf.name}}

{{itemc.created_at}}
打賞
已打賞¥{{itemc.reward_price}}
{{itemc.like_count}}
{{itemc.showReply ? '取消回復(fù)' : '回復(fù)'}}
刪除
回復(fù)
回復(fù)
查看更多
打賞
已打賞¥{{reward_price}}
99
{{like_count}}
{{collect_count}}
添加回復(fù) ({{post_count}})

相關(guān)推薦

快速安全登錄

使用微信掃碼登錄
{{item.label}} 加精
{{item.label}} {{item.label}} 板塊推薦 常見問題 產(chǎn)品動(dòng)態(tài) 精選推薦 首頁頭條 首頁動(dòng)態(tài) 首頁推薦
取 消 確 定
回復(fù)
回復(fù)
問題:
問題自動(dòng)獲取的帖子內(nèi)容,不準(zhǔn)確時(shí)需要手動(dòng)修改. [獲取答案]
答案:
提交
bug 需求 取 消 確 定
打賞金額
當(dāng)前余額:¥{{rewardUserInfo.reward_price}}
{{item.price}}元
請(qǐng)輸入 0.1-{{reward_max_price}} 范圍內(nèi)的數(shù)值
打賞成功
¥{{price}}
完成 確認(rèn)打賞

微信登錄/注冊(cè)

切換手機(jī)號(hào)登錄

{{ bind_phone ? '綁定手機(jī)' : '手機(jī)登錄'}}

{{codeText}}
切換微信登錄/注冊(cè)
暫不綁定
CRMEB客服

CRMEB咨詢熱線 咨詢熱線

400-8888-794

微信掃碼咨詢

CRMEB開源商城下載 源碼下載 CRMEB幫助文檔 幫助文檔
返回頂部 返回頂部
CRMEB客服