針對鈴聲多多官網(shoujiduoduo.com)的公開 API 接口,設計高併發多線程爬蟲,實現鈴聲列表分頁抓取、詳情解析、下載鏈接獲取、數據持久化全流程。
| 功能 | 接口地址 | 關鍵參數 |
|---|---|---|
| 列表接口 | /ringweb/ringweb.php?type=getlist | listid(分類ID), page(頁碼) |
| 下載接口 | /ringweb/ringweb.php?type=geturl&act=down | rid(鈴聲ID) |
列表返回 JSON 含 hasmore(是否有下一頁)和 curpage(當前頁碼),作為翻頁終止條件。
LinkedBlockingQueue 解耦,背壓自動控制// 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()
);
@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;
}
原始返回包含尾部統計對象 {"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());
User-Agent、RefererThread.sleep(random.nextInt(200) + 100)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)
crawl:progress:{listId} = 當前頁碼CrawlTask 提交到線程池hasmore=0 或達到 endPage 停止該分類⚠️ 重要:爬蟲僅供技術學習研究,實際使用必須:
robots.txt 協議本文展示的架構模式(生產消費分離、線程池隔離、斷點續傳、數據校驗)適用於絕大多數公開 API 爬取場景,是 Java 爬蟲工程化的標準範式。