使用springboot+vw-crawler輕鬆抓取CSDN的文章
有關VW-Cralwer的介紹可以看這裏,簡單輕便開源的一款Java爬蟲框架。
下面結合比較流行的框架SpringBoot抓取CSDN的數據(有關的Spingboot的使用可以參考這裏)
配置POM
使用Springboot做架構,redis做數據存儲,vw-crawler做爬蟲模塊,最終的pom如下
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<vw-crawler.version>0.0.4</vw-crawler.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<!--這裏不需要web服務,只需要Application即可-->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.vector4wang</groupId>
<artifactId>vw-crawler</artifactId>
<version>0.0.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.7</version>
</dependency>
</dependencies>
redis相關配置
因爲已經添加了redis的相關依賴,只需要在application.properties裏配置redis的鏈接參數即可,如下
# Redis數據庫索引(默認爲0)
spring.redis.database=1
# Redis服務器地址
spring.redis.host=localhost
# Redis服務器連接端口
spring.redis.port=6379
# Redis服務器連接密碼(默認爲空)
spring.redis.password=
# 連接池最大連接數(使用負值表示沒有限制)
spring.redis.pool.max-active=8
# 連接池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.pool.max-wait=-1
# 連接池中的最大空閒連接
spring.redis.pool.max-idle=8
# 連接池中的最小空閒連接
spring.redis.pool.min-idle=0
# 連接超時時間(毫秒)
spring.redis.timeout=0
代碼裏的使用
@Component
public class DataCache {
@Autowired
private StringRedisTemplate redisTemplate;
public void save(Blog blog) {
redisTemplate.opsForValue().set(blog.getUrlMd5(), JSON.toJSONString(blog));
}
public Blog get(String url) {
String md5Url = Md5Util.getMD5(url.getBytes());
String blogStr = redisTemplate.opsForValue().get(md5Url);
if (StringUtils.isEmpty(blogStr)) {
return new Blog();
}
return JSON.parseObject(blogStr, Blog.class);
}
}
比較簡單,一個保存一個獲取即可,這裏使用StringRedisTemplate時爲了更直觀的在redis客戶端中查看內容。
爬蟲
頁面數據model
使用流行的註解方式來填充數據
@CssSelector(selector = "#mainBox > main > div.blog-content-box > div.article-title-box > h1", resultType = SelectType.TEXT)
private String title;
@CssSelector(selector = "#mainBox > main > div.blog-content-box > div.article-info-box > div > span.time", dateFormat = "yyyy年MM月dd日 HH:mm:ss")
private Date publishDate;
@CssSelector(selector = "#mainBox > main > div.blog-content-box > div.article-info-box > div > div > span", resultType = SelectType.TEXT)
private String readCountStr;
private int readCount;
@CssSelector(selector = "#article_content",resultType = SelectType.TEXT)
private String content;
@CssSelector(selector = "body > div.tool-box > ul > li:nth-child(1) > button > p",resultType = SelectType.TEXT)
private int likeCount;
/**
* 暫時不支持自動解析列表的功能,所以加個中間變量,需要二次解析下
*/
@CssSelector(selector = "#mainBox > main > div.comment-box > div.comment-list-container > div.comment-list-box",resultType = SelectType.HTML)
private String comentTmp;
private String url;
private String urlMd5;
private List<String> comment;
使用選擇器來精確定位數據,使用chrome瀏覽器的可以這樣快速獲取
如圖,也支持xpath的快捷選擇(vw-crawler後續會支持xpath定位元素),當然了,有些元素如”閱讀數:xxx”,是不能自動轉化爲整型,所以還需要第二次解析處理
爬蟲配置
這裏需要配置請求頭如“User-Agent”,目標頁URL的正則表達式,列表頁URL的正則,還有爬蟲的線程數和超時等等,如下
new VWCrawler.Builder().setUrl("https://blog.csdn.net/qqhjqs").setHeader("User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36")
.setTargetUrlRex("https://blog.csdn.net/qqhjqs/article/details/[0-9]+").setThreadCount(5)
.setTimeOut(5000).setPageParser(new CrawlerService<Blog>() {
@Override
public void parsePage(Document doc, Blog pageObj) {
pageObj.setReadCount(Integer.parseInt(pageObj.getReadCountStr().replace("閱讀數:", "")));
pageObj.setUrl(doc.baseUri());
pageObj.setUrlMd5(Md5Util.getMD5(pageObj.getUrl().getBytes()));
}
@Override
public void save(Blog pageObj) {
dataCache.save(pageObj);
}
}).build().start();
需要實現CrawlerService,看下源碼
public boolean isExist(String url){
return false;
}
public boolean isContinue(Document document){
if (document == null) {
return false;
}
return true;
}
public abstract void parsePage(Document doc, T pageObj);
public abstract void save(T pageObj);
可以看到parsePage可以處理數據的二次解析,save則負責保存數據,isExist和isContinue是處理爬取過程中的一些判斷邏輯
- isExist 是url的二次判重,你可以通過查找數據庫來判斷即將要抓取的URL是否存在數據庫中,存在則返回true,不存則正常抓取即返回false;
- isContinue 是在解析頁面數據前判斷一下該頁面是否有WAF(Web Application Firewal),如果有則返回false,沒有則正常進行解析即返回true;
要在springboot全部初始化完畢之後再去啓動爬蟲, 所有需要這樣配置
@Component
@Order
public class Crawler implements CommandLineRunner {
@Autowired
private DataCache dataCache;
@Override
public void run(String... strings) {
// 爬蟲配置
}
}
啓動
直接右鍵執行CrawlerApplication即可
最終抓取如圖
相關鏈接
該爬蟲地址:傳送門