用springboot+vw-crawler輕鬆抓取CSDN的文章

使用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瀏覽器的可以這樣快速獲取
WX20180722-103513@2x.png
如圖,也支持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即可
最終抓取如圖
WX20180722-110714@2x.png

相關鏈接

VW-Crawler SpringBoot

該爬蟲地址:傳送門

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章