本文通過實戰項目,演示如何使用 Jsoup 庫構建高效的 CSDN 博客文章爬蟲,涵蓋從單頁採集到全站分頁採集的完整流程,包含反爬應對、代理配置、數據解析與持久化等工程化實踐。
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.10.2</version>
</dependency>
以博主「郭霖」(guolin_blog) 為例,通過開發者工具分析:
div#article_list.listdiv.list_item.article_item
div.article_title h1 span.link_title adiv.article_descriptiondiv.article_manage span.link_postdate (時間)、span.link_view (閱讀數)、span.link_comments (評論數)div#papelist.pagelist
span:eq(0) → "100條 共7頁"public class Article {
private String address; // 相對鏈接
private String title;
private String description;
private String time;
// Getter/Setter 省略
}
public List<Article> getArticlesByPage(int pageNum) throws IOException {
String url = "https://blog.csdn.net/guolin_blog/article/list/" + pageNum;
Connection conn = Jsoup.connect(url)
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
.timeout(5000)
.method(Connection.Method.GET);
Document doc = conn.get();
Element body = doc.body();
Element articleListDiv = body.getElementById("article_list");
Elements articleItems = articleListDiv.getElementsByClass("list_item");
List<Article> result = new ArrayList<>();
for (Element item : articleItems) {
Article article = new Article();
Element linkEl = item.select("div.article_title h1 a").first();
Element descEl = item.getElementsByClass("article_description").first();
Element metaEl = item.getElementsByClass("article_manage").first();
article.setAddress(linkEl.attr("href"));
article.setTitle(linkEl.text());
article.setDescription(descEl.text());
article.setTime(metaEl.select("span:eq(0)").text()); // 發布時間
result.add(article);
}
return result;
}
public List<Article> crawlAllArticles() throws IOException {
// 1. 獲取首頁確定總頁數
Document firstPage = Jsoup.connect("https://blog.csdn.net/guolin_blog")
.userAgent(UA).timeout(5000).get();
String pageInfo = firstPage.getElementById("papelist")
.select("span:eq(0)").text(); // "100條 共7頁"
// 2. 正則提取總頁數
int totalPages = Integer.parseInt(
pageInfo.replaceAll(".+共(\\d+)頁", "$1")
);
// 3. 逐頁採集聚合
List<Article> allArticles = new ArrayList<>();
for (int i = 1; i <= totalPages; i++) {
allArticles.addAll(getArticlesByPage(i));
// 禮貌延遲,避免觸發反爬
Thread.sleep(1000 + new Random().nextInt(2000));
}
return allArticles;
}
timeout(5000) (5秒),過短導致 SocketTimeoutExceptionSystem.setProperty("http.maxRedirects", "50");
System.getProperties().setProperty("proxySet", "true");
System.getProperties().setProperty("http.proxyHost", "代理IP");
System.getProperties().setProperty("http.proxyPort", "代理端口");
// 若需認證
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("user", "pass".toCharArray());
}
});
User-Agent,模擬瀏覽器指紋Connection 對象保持 Cookiecsdn-crawler/ ├── src/main/java/ │ ├── model/Article.java │ ├── crawler/CsdnCrawler.java │ └── util/RegexUtils.java ├── pom.xml └── README.md
重要提醒:爬蟲開發必須遵守:
robots.txt協議- 網站服務條款 (ToS)
- 《計算機信息網絡國際聯網管理暫行規定》等法律法規
- 控制採集頻率,不影響目標站點正常服務
- 僅採集公開數據,不繞過登錄/驗證機制
Jsoup 以其鏈式 API、CSS 選擇器、容錯解析能力,成為 Java 爬蟲開發的首選工具。本文從頁面分析、單頁解析、分頁策略、反爬應對到工程化落地,提供了完整的 CSDN 博客採集實戰指南。代碼已開源托管,歡迎技術交流共同進步。