首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 多線程爬蟲實戰:鈴聲多多數據抓取完整架構

     編輯:Java 相關知識

項目背景與目標

針對鈴聲多多官網(shoujiduoduo.com)的公開 API 接口,設計高併發多線程爬蟲,實現鈴聲列表分頁抓取、詳情解析、下載鏈接獲取、數據持久化全流程。

接口分析

功能接口地址關鍵參數
列表接口/ringweb/ringweb.php?type=getlistlistid(分類ID), page(頁碼)
下載接口/ringweb/ringweb.php?type=geturl&act=downrid(鈴聲ID)

列表返回 JSON 含 hasmore(是否有下一頁)和 curpage(當前頁碼),作為翻頁終止條件。

核心架構設計

1. 生產者-消費者模式

  • 生產者線程:按分類 ID 分配任務,調用列表接口,解析 JSON,將鈴聲對象放入阻塞隊列
  • 消費者線程池:從隊列取數據,調用下載接口獲取真實 URL,持久化到數據庫/文件
  • 使用 LinkedBlockingQueue 解耦,背壓自動控制

2. 線程池配置

// IO 密集型任務,核心線程數 = CPU核心數 * 2
private static final ExecutorService DOWNLOAD_POOL = 
    new ThreadPoolExecutor(
        8, 16, 60L, TimeUnit.SECONDS,
        new LinkedBlockingQueue<>(1000),
        new ThreadFactoryBuilder().setNameFormat("ring-downloader-%d").build(),
        new ThreadPoolExecutor.AbortPolicy()
    );

3. 實體類設計

@Data
@Builder
public class RingTone {
    private String id;
    private String name;
    private String artist;
    private String duration; // 秒數,需校驗純數字
    private String categoryId;
    private String downloadUrl; // 二次請求獲取
    private LocalDateTime crawlTime;
}

關鍵技術難點與解決

1. JSON 清洗與解析

原始返回包含尾部統計對象 {"hasmore":1,"curpage":1},需預處理:

// 移除尾部統計對象,修復非標準 JSON 數組結尾
String cleanJson = rawJson
    .replaceAll("\\{\"hasmore\":\\d+,\"curpage\":\\d+\\},?", "")
    .replaceAll(",?\\s*\\]", "]");
    
JsonArray array = JsonParser.parseString(cleanJson).getAsJsonArray();
List rings = new Gson().fromJson(array, new TypeToken>(){}.getType());

2. 反爬與限流應對

  • 設置合理 User-Agent、Referer
  • 請求間隔隨機化:Thread.sleep(random.nextInt(200) + 100)
  • IP 代理池輪換(生產環境必備)
  • 識別 429/403 狀態碼,指數退避重試

3. 數據去重與校驗

private boolean isValid(RingTone ring) {
    return ring != null 
        && StringUtils.isNumeric(ring.getDuration()) // 時長必須純數字
        && ring.getName().length() <= 50
        && ring.getArtist().length() <= 50
        && StringUtils.isNotBlank(ring.getDownloadUrl());
}

// 數據庫唯一索引:UNIQUE KEY uk_ring_id (id)

4. 斷點續爬機制

  • Redis 記錄 crawl:progress:{listId} = 當前頁碼
  • 啟動時讀取進度,跳過已抓取頁面
  • 異常時自動保存進度,支持故障恢復

完整運行流程

  1. 主線程讀取配置(分類 ID 列表、起始頁、結束頁、線程數)
  2. 為每個分類創建 CrawlTask 提交到線程池
  3. 任務循環:請求列表 → 解析 → 入隊 → 消費者處理下載鏈接 → 入庫
  4. 遇到 hasmore=0 或達到 endPage 停止該分類
  5. 所有任務完成,關閉線程池,輸出統計報表

法律與道德提醒

⚠️ 重要:爬蟲僅供技術學習研究,實際使用必須:

  • 遵守目標站點 robots.txt 協議
  • 控制請求頻率,不影響正常服務
  • 不繞過登錄/驗證碼等訪問控制
  • 數據不用於商業用途,尊重版權與知識產權

本文展示的架構模式(生產消費分離、線程池隔離、斷點續傳、數據校驗)適用於絕大多數公開 API 爬取場景,是 Java 爬蟲工程化的標準範式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved