目標頁面結構:
<div id="songListWrapper">
<ul>
<li class="bb-dotimg clearfix song-item-hook {'songItem':{'sid':'113275822','sname':'我的要求不算高','author':'黃渤'}}">...</li>
...
</ul>
</div>
List<Mp3> mp3List = new ArrayList<>();
try {
Parser parser = new Parser(htmlString); // 或 new Parser(url)
parser.setEncoding("UTF-8");
// 1. 組合過濾器:div + id="songListWrapper"
NodeFilter filter = new AndFilter(
new TagNameFilter("div"),
new HasAttributeFilter("id", "songListWrapper")
);
NodeList wrapperNodes = parser.parse(filter);
Node wrapper = wrapperNodes.elementAt(0);
// 2. 層層下鑽:div → ul → li[]
Node ul = wrapper.getChildren().elementAt(1).getChildren().elementAt(1);
Node[] liNodes = ul.getChildren().toNodeArray();
// 3. 遍歷 li,提取 class 屬性
for (int i = 2; i < liNodes.length; i++) { // 跳過表頭
Node li = liNodes[i];
TagNode tag = new TagNode();
tag.setText(li.toHtml()); // 轉 TagNode 才能 getAttribute
String cls = tag.getAttribute("class").replaceAll("\\s+", "");
// 4. 正則提取 JSON 字段
Pattern p = Pattern.compile(
".*\\{'songItem':\\{'sid':'(\\d+)','sname':'([^']+)','author':'([^']+)'\\}\\}.*"
);
Matcher m = p.matcher(cls);
if (m.find()) {
Mp3 mp3 = new Mp3();
mp3.setSid(m.group(1));
mp3.setSname(m.group(2));
mp3.setAuthor(m.group(3));
mp3List.add(mp3);
}
}
} catch (Exception e) { e.printStackTrace(); }
AndFilter 實現多條件 AND 查找;TagNode 才有 getAttribute(),需手動 setText(node.toHtml()) 轉換;.* 前後包裹,容忍 class 中其他樣式類名;parser.setEncoding("UTF-8") 防止中文亂碼。doc.select("div#songListWrapper li"));理解「過濾器鏈 → DOM 樹遍歷 → 屬性提取 → 正則解析」四步曲,遷移到任何解析庫皆通用。