一、前言
WebMagic
:一款簡單靈活的爬蟲框架,基於它我們可以非常容易的編寫一個爬蟲。- 官網文檔地址:http://webmagic.io/docs/zh/
下面小編將通過爬取+解析自己的csdn文章數據來演示一個簡單的爬蟲案例demo
二、SpringBoot 整合 WebMagic
1、pom.xml
中引入相關依賴
<!-- WebMagic:爬蟲 -->
<dependency>
<groupId>us.codecraft</groupId>
<artifactId>webmagic-core</artifactId>
<version>0.7.3</version>
</dependency>
<dependency>
<groupId>us.codecraft</groupId>
<artifactId>webmagic-extension</artifactId>
<version>0.7.3</version>
</dependency>
2、定義全局常用變量-博主博客地址
public class Constants {
/**
* csdn博主博客地址
*/
public static final String CSDN_URL = "https://blog.csdn.net/qq_38225558/article/list/1";
}
3、CSDN博客文章信息實體類
@Data
@AllArgsConstructor
public class Csdn {
/**
* id
*/
private int id;
/**
* 文章標題
*/
private String title;
/**
* 文章發佈時間
*/
private String time;
/**
* 文章所屬分類
*/
private String category;
/**
* 文章內容
*/
private String content;
}
4、編寫一個簡單的爬蟲
實現PageProcessor
類
@Slf4j
public class SamplePageProcessor implements PageProcessor {
/**
* 記錄總分頁列表url數
*/
private static List<String> urlList = new ArrayList<>();
/**
* 文章詳情信息
*/
private static List<Csdn> articleDetailInfoList = new ArrayList<>();
/**
* 【部分一】:抓取網站的相關配置,包括編碼、抓取間隔、重試次數等
*/
private Site site = Site.me().
// 重試次數
setRetryTimes(3).
// 抓取間隔
setSleepTime(1000).
// 超時時間
setTimeOut(100 * 1000);
/**
* process是定製爬蟲邏輯的核心接口,在這裏編寫抽取邏輯
*
* @param page:
* 頁面數據
* @return: void
* @author : zhengqing
* @date : 2020/7/1 16:43
*/
@Override
public void process(Page page) {
// 【部分二】:定義如何抽取頁面信息,並保存下來
Html html = page.getHtml();
// 根據url判斷該頁面屬於列表頁還是文章詳情頁面
String url = page.getUrl().toString();
log.info("頁面url地址:【{}】", url);
if (url.contains("article/details")) {
// 詳情頁面處理邏輯...
// 文章id
int articleId = Integer.parseInt(url.substring(url.lastIndexOf('/') + 1));
// 文章標題
String articleTitle = html.xpath("//h1[@class='title-article']//text()").toString();
// 文章發佈時間
String articleTime = html.xpath("//div[@class='bar-content']//span[@class='time']//text()").toString();
// 文章所屬分類
String articleCategory = html.xpath("//a[@class='tag-link']//text()").toString();
// 文章內容
String articleContent = html.xpath("//article[@class='baidu_pl']").toString();
log.info("文章id:【{}】 文章標題:【{}】 文章所屬分類:【{}】", articleId, articleTitle, articleCategory);
Csdn csdn = new Csdn(articleId, articleTitle, articleTime, articleCategory, articleContent);
if (articleDetailInfoList.contains(csdn)) {
return;
}
articleDetailInfoList.add(csdn);
} else if (url.contains("article/list")) {
// 列表頁面處理邏輯...
if (urlList.contains(url)) {
return;
}
urlList.add(url);
List<Selectable> articleList = html
.xpath("//div[@class='article-list']//div[@class='article-item-box csdn-tracking-statistics']").nodes();
if (CollectionUtils.isEmpty(articleList)) {
// 這裏移除最後一條錯誤元素
urlList.remove(urlList.get(urlList.size() - 1));
log.info("總列表數:【{}】 總文章數:【{}】", urlList, articleDetailInfoList);
return;
}
// 開始解析每一篇文章數據【文章標題,發送時間,文章詳情url地址】
articleList.forEach(article -> {
// 文章標題
String articleTitle = article.$("a", "text").toString();
// 文章詳情url地址
String articleUrl = article.links().toString();
// 文章發佈時間
String articleTime =
article.xpath("//div[@class='info-box d-flex align-content-center']//span[@class='date']/text()")
.toString();
log.info("文章標題:【{}】 文章地址:【{}】 文章發佈時間:【{}】", articleTitle, articleUrl, articleTime);
// 進入文章內部獲取文章詳情內容
page.addTargetRequests(article.links().all());
});
// 【部分三】:從頁面發現後續的url地址來抓取 (這裏因csdn暫時拿不了頁面尾部的分頁數,因此手動模擬了一下數據...)
int nextPage = Integer.parseInt(url.substring(url.lastIndexOf('/') + 1)) + 1;
String newUrl = "https://blog.csdn.net/qq_38225558/article/list/" + nextPage;
page.addTargetRequest(newUrl);
} else {
// Other ...
log.error("該頁面url【{}】無法解析...", url);
}
}
@Override
public Site getSite() {
return site;
}
public static void main(String[] args) {
Spider.create(new SamplePageProcessor())
// 從指定的url地址開始抓
.addUrl(Constants.CSDN_URL)
// 開啓5個線程抓取
.thread(5)
// 啓動爬蟲
.run();
}
}
5、定時器定時爬取數據
這部分看自己需求,不是必要…
① 啓動類開啓定時任務
② 編寫定時任務
@Slf4j
@Component
public class AppScheduledJobs {
/**
* 每10秒執行一次
*
* @return: void
* @author : zhengqing
* @date : 2020/7/1 11:44
*/
@Scheduled(cron = "*/10 * * * * ?")
public void cralwer() {
log.info("<<<<<< Start: 【{}】 >>>>>>", LocalDateTime.now());
Spider.create(new SamplePageProcessor())
// .setDownloader(new HttpClientDownloader())
// 從指定的url地址開始抓
.addUrl(Constants.CSDN_URL)
// 開啓5個線程抓取
.thread(5)
// 啓動爬蟲
.run();
}
}
三、運行項目測試
可以看到我們解析獲取到的文章標題,文章內容,文章發佈時間等一系列信息…