[关闭]
@xiaoxiaowang 2018-07-22T03:21:11.000000Z 字数 4709 阅读 1369

使用springboot+vw-crawler轻松抓取CSDN的文章

Java Spring Springboot 爬虫 爬虫框架


有关VW-Cralwer的介绍可以看这里,简单轻便开源的一款Java爬虫框架。

下面结合比较流行的框架SpringBoot抓取CSDN的数据(有关的Spingboot的使用可以参考这里)

配置POM

使用Springboot做架构,redis做数据存储,vw-crawler做爬虫模块,最终的pom如下

  1. <parent>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-parent</artifactId>
  4. <version>1.4.3.RELEASE</version>
  5. <relativePath/> <!-- lookup parent from repository -->
  6. </parent>
  7. <properties>
  8. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  9. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  10. <java.version>1.8</java.version>
  11. <vw-crawler.version>0.0.4</vw-crawler.version>
  12. </properties>
  13. <dependencies>
  14. <dependency>
  15. <groupId>org.springframework.boot</groupId>
  16. <artifactId>spring-boot-starter-web</artifactId>
  17. <exclusions>
  18. <exclusion>
  19. <!--这里不需要web服务,只需要Application即可-->
  20. <groupId>org.springframework.boot</groupId>
  21. <artifactId>spring-boot-starter-tomcat</artifactId>
  22. </exclusion>
  23. </exclusions>
  24. </dependency>
  25. <dependency>
  26. <groupId>com.github.vector4wang</groupId>
  27. <artifactId>vw-crawler</artifactId>
  28. <version>0.0.5</version>
  29. </dependency>
  30. <dependency>
  31. <groupId>org.springframework.boot</groupId>
  32. <artifactId>spring-boot-starter-redis</artifactId>
  33. </dependency>
  34. <dependency>
  35. <groupId>com.alibaba</groupId>
  36. <artifactId>fastjson</artifactId>
  37. <version>1.2.7</version>
  38. </dependency>
  39. </dependencies>

redis相关配置

因为已经添加了redis的相关依赖,只需要在application.properties里配置redis的链接参数即可,如下

  1. # Redis数据库索引(默认为0)
  2. spring.redis.database=1
  3. # Redis服务器地址
  4. spring.redis.host=localhost
  5. # Redis服务器连接端口
  6. spring.redis.port=6379
  7. # Redis服务器连接密码(默认为空)
  8. spring.redis.password=
  9. # 连接池最大连接数(使用负值表示没有限制)
  10. spring.redis.pool.max-active=8
  11. # 连接池最大阻塞等待时间(使用负值表示没有限制)
  12. spring.redis.pool.max-wait=-1
  13. # 连接池中的最大空闲连接
  14. spring.redis.pool.max-idle=8
  15. # 连接池中的最小空闲连接
  16. spring.redis.pool.min-idle=0
  17. # 连接超时时间(毫秒)
  18. spring.redis.timeout=0

代码里的使用

  1. @Component
  2. public class DataCache {
  3. @Autowired
  4. private StringRedisTemplate redisTemplate;
  5. public void save(Blog blog) {
  6. redisTemplate.opsForValue().set(blog.getUrlMd5(), JSON.toJSONString(blog));
  7. }
  8. public Blog get(String url) {
  9. String md5Url = Md5Util.getMD5(url.getBytes());
  10. String blogStr = redisTemplate.opsForValue().get(md5Url);
  11. if (StringUtils.isEmpty(blogStr)) {
  12. return new Blog();
  13. }
  14. return JSON.parseObject(blogStr, Blog.class);
  15. }
  16. }

比较简单,一个保存一个获取即可,这里使用StringRedisTemplate时为了更直观的在redis客户端中查看内容。

爬虫

页面数据model

使用流行的注解方式来填充数据

  1. @CssSelector(selector = "#mainBox > main > div.blog-content-box > div.article-title-box > h1", resultType = SelectType.TEXT)
  2. private String title;
  3. @CssSelector(selector = "#mainBox > main > div.blog-content-box > div.article-info-box > div > span.time", dateFormat = "yyyy年MM月dd日 HH:mm:ss")
  4. private Date publishDate;
  5. @CssSelector(selector = "#mainBox > main > div.blog-content-box > div.article-info-box > div > div > span", resultType = SelectType.TEXT)
  6. private String readCountStr;
  7. private int readCount;
  8. @CssSelector(selector = "#article_content",resultType = SelectType.TEXT)
  9. private String content;
  10. @CssSelector(selector = "body > div.tool-box > ul > li:nth-child(1) > button > p",resultType = SelectType.TEXT)
  11. private int likeCount;
  12. /**
  13. * 暂时不支持自动解析列表的功能,所以加个中间变量,需要二次解析下
  14. */
  15. @CssSelector(selector = "#mainBox > main > div.comment-box > div.comment-list-container > div.comment-list-box",resultType = SelectType.HTML)
  16. private String comentTmp;
  17. private String url;
  18. private String urlMd5;
  19. private List<String> comment;

使用选择器来精确定位数据,使用chrome浏览器的可以这样快速获取
WX20180722-103513@2x.png
如图,也支持xpath的快捷选择(vw-crawler后续会支持xpath定位元素),当然了,有些元素如"阅读数:xxx",是不能自动转化为整型,所以还需要第二次解析处理

爬虫配置

这里需要配置请求头如“User-Agent”,目标页URL的正则表达式,列表页URL的正则,还有爬虫的线程数和超时等等,如下

  1. new VWCrawler.Builder().setUrl("https://blog.csdn.net/qqhjqs").setHeader("User-Agent",
  2. "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36")
  3. .setTargetUrlRex("https://blog.csdn.net/qqhjqs/article/details/[0-9]+").setThreadCount(5)
  4. .setTimeOut(5000).setPageParser(new CrawlerService<Blog>() {
  5. @Override
  6. public void parsePage(Document doc, Blog pageObj) {
  7. pageObj.setReadCount(Integer.parseInt(pageObj.getReadCountStr().replace("阅读数:", "")));
  8. pageObj.setUrl(doc.baseUri());
  9. pageObj.setUrlMd5(Md5Util.getMD5(pageObj.getUrl().getBytes()));
  10. }
  11. @Override
  12. public void save(Blog pageObj) {
  13. dataCache.save(pageObj);
  14. }
  15. }).build().start();

需要实现CrawlerService,看下源码

  1. public boolean isExist(String url){
  2. return false;
  3. }
  4. public boolean isContinue(Document document){
  5. if (document == null) {
  6. return false;
  7. }
  8. return true;
  9. }
  10. public abstract void parsePage(Document doc, T pageObj);
  11. public abstract void save(T pageObj);

可以看到parsePage可以处理数据的二次解析,save则负责保存数据,isExist和isContinue是处理爬取过程中的一些判断逻辑

要在springboot全部初始化完毕之后再去启动爬虫, 所有需要这样配置

  1. @Component
  2. @Order
  3. public class Crawler implements CommandLineRunner {
  4. @Autowired
  5. private DataCache dataCache;
  6. @Override
  7. public void run(String... strings) {
  8. // 爬虫配置
  9. }
  10. }

启动

直接右键执行CrawlerApplication即可
最终抓取如图
WX20180722-110714@2x.png

相关链接

VW-Crawler SpringBoot

该爬虫地址:传送门





添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注