当前位置:   article > 正文

SpringBoot从入门到精通教程(三十一)- 爬虫框架集成_springboot爬虫教程

springboot爬虫教程

需求背景

SpringBoot用法:爬虫框架集成

业务场景

以抓取“今日头条”新闻举例说明

技术点

1. 集成爬虫框架webmagic(更多了解webmagic,可以去官方地址

  1. <dependency>
  2. <groupId>us.codecraft</groupId>
  3. <artifactId>webmagic-extension</artifactId>
  4. <version>0.6.0</version>
  5. </dependency>

WebMagic是一个简单灵活的Java爬虫框架。基于WebMagic,你可以快速开发出一个高效、易维护的爬虫程序

特性:

  1. 简单的API,可快速上手
  2. 模块化的结构,可轻松扩展
  3. 提供多线程和分布式支持

代码演示

1. 项目目录结构

2. pom.xml依赖组件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <parent>
  7. <groupId>com.md</groupId>
  8. <artifactId>spring-boot2-parent</artifactId>
  9. <version>0.0.1-SNAPSHOT</version>
  10. <relativePath>../pom.xml</relativePath>
  11. </parent>
  12. <artifactId>spring-boot2-crawler</artifactId>
  13. <packaging>jar</packaging>
  14. <name>spring-boot2-crawler</name>
  15. <description>Spring Boot, MVC, Rest API for App</description>
  16. <properties>
  17. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  18. <java.version>1.8</java.version>
  19. </properties>
  20. <dependencies>
  21. <dependency>
  22. <groupId>org.springframework.boot</groupId>
  23. <artifactId>spring-boot-starter</artifactId>
  24. </dependency>
  25. <!-- 构建成可运行的Web项目 -->
  26. <dependency>
  27. <groupId>org.springframework.boot</groupId>
  28. <artifactId>spring-boot-starter-web</artifactId>
  29. </dependency>
  30. <dependency>
  31. <groupId>net.sf.json-lib</groupId>
  32. <artifactId>json-lib-ext-spring</artifactId>
  33. </dependency>
  34. <dependency>
  35. <groupId>org.projectlombok</groupId>
  36. <artifactId>lombok</artifactId>
  37. <optional>true</optional>
  38. </dependency>
  39. <!-- webmagic 爬虫工具类 -->
  40. <dependency>
  41. <groupId>us.codecraft</groupId>
  42. <artifactId>webmagic-extension</artifactId>
  43. <version>0.6.0</version>
  44. </dependency>
  45. <dependency>
  46. <groupId>org.nlpcn</groupId>
  47. <artifactId>nlp-lang</artifactId>
  48. <version>1.7</version>
  49. </dependency>
  50. </dependencies>
  51. <build>
  52. <plugins>
  53. <plugin>
  54. <groupId>org.springframework.boot</groupId>
  55. <artifactId>spring-boot-maven-plugin</artifactId>
  56. </plugin>
  57. </plugins>
  58. </build>
  59. </project>

3. 爬虫核心解析类

MyPageProcessor:

  1. package com.md.demo.crawler.test;
  2. import java.util.List;
  3. import org.nlpcn.commons.lang.finger.SimHashService;
  4. import lombok.extern.slf4j.Slf4j;
  5. import us.codecraft.webmagic.Page;
  6. import us.codecraft.webmagic.Site;
  7. import us.codecraft.webmagic.Spider;
  8. import us.codecraft.webmagic.processor.PageProcessor;
  9. import us.codecraft.webmagic.selector.JsonPathSelector;
  10. /**
  11. * 官方地址:http://webmagic.io/
  12. *
  13. * WebMagic是一个简单灵活的Java爬虫框架。基于WebMagic,你可以快速开发出一个高效、易维护的爬虫。
  14. *
  15. * @author Minbo
  16. *
  17. */
  18. @Slf4j
  19. public class MyPageProcessor implements PageProcessor {
  20. private Site site = Site.me();
  21. @Override
  22. public void process(Page page) {
  23. // 这里使用了jsonPath,因为今日头条返回的是json数据格式。如果是html内容,则使用xpath
  24. // 第一层解析
  25. String json = page.getRawText();
  26. List<String> data = new JsonPathSelector("$.data").selectList(json);
  27. // 第二层解析
  28. for (int i = 0; i < data.size(); i++) {
  29. String result = data.get(i);
  30. // 文章ID
  31. String item_id = new JsonPathSelector("$.item_id").select(result);
  32. // 文章标题
  33. String title = new JsonPathSelector("$.title").select(result);
  34. // 是否有图
  35. String has_image = new JsonPathSelector("$.has_image").select(result);
  36. // 文章来源
  37. String source = new JsonPathSelector("$.source").select(result);
  38. // 文章时间
  39. String datetime = new JsonPathSelector("$.datetime").select(result);
  40. // 一般是根据文章详细内容生成内容指纹id,实现文章去重,这里只是举例说明拿了文章标题
  41. // 更多阅读我的博客文章:https://blog.csdn.net/hemin1003/article/details/82819489(【应用算法】信息流-推荐系统的去重策略)
  42. String fPrintId = String.valueOf(new SimHashService().fingerprint(title));
  43. log.info("");
  44. log.info("---------->>> 提取文章主信息:");
  45. log.info("文章ID item_id=" + item_id);
  46. log.info("文章标题 title=" + title);
  47. log.info("是否有图 has_image=" + has_image);
  48. log.info("文章来源 source=" + source);
  49. log.info("文章时间 datetime=" + datetime);
  50. log.info("内容指纹id fPrintId=" + fPrintId);
  51. // webmagic官方还有很多案例,更多内容自行参考学习了,例如配置代理,自带url去重、网页去重等功能
  52. // 官方文档地址:http://webmagic.io/docs/zh/
  53. }
  54. }
  55. public Site getSite() {
  56. return MySite.getSit(site);
  57. }
  58. public static void main(String[] args) {
  59. // 今日头条/热点数据url
  60. Spider.create(new MyPageProcessor()).addUrl(
  61. "https://m.toutiao.com/list/?tag=news_hot&ac=wap&count=20&format=json_raw&as=A1551E75BC4CF9C&cp=5E5C3CEFB9DCAE1&max_behot_time=1583123351&_signature=CXZIuwAAVy.txcPhjSEcTwl2SK&i=1583123351")
  62. .thread(1).run();
  63. }
  64. }

MySite:

  1. package com.md.demo.crawler.test;
  2. import us.codecraft.webmagic.Site;
  3. /**
  4. * 模拟请求头设置
  5. *
  6. * @author Minbo
  7. *
  8. */
  9. public class MySite {
  10. // 设置请求头
  11. public static Site getSit(Site site) {
  12. site.addHeader("Accept", "*/*");
  13. site.addHeader("Accept-Encoding", "gzip, deflate, br");
  14. site.addHeader("Accept-Language", "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,zh-TW;q=0.6,cy;q=0.5");
  15. site.addHeader("Connection", "keep-alive");
  16. site.addHeader("Cookie",
  17. "uuid=\"w:6eeae48e765542f8816b14bd1a8803f2\"; tt_webid=6799537520192783879; csrftoken=3eb88bcad1818058de0e3c0ca8a3f6d1; W2atIF=1; _ga=GA1.2.2115719807.1583140719; _gid=GA1.2.359266539.1583140719; __tasessionId=tr7vk2kgh1583140721519");
  18. site.addHeader("Host", "m.toutiao.com");
  19. site.addHeader("Referer", "https://m.toutiao.com/?w2atif=1&channel=news_hot");
  20. site.addHeader("Sec-Fetch-Dest", "empty");
  21. site.addHeader("Sec-Fetch-Mode", "cors");
  22. site.addHeader("Sec-Fetch-Site", "same-origin");
  23. site.addHeader("Upgrade-Insecure-Requests", "1");
  24. site.addHeader("User-Agent",
  25. "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1");
  26. site.setTimeOut(60000);
  27. site.setCharset("UTF-8");
  28. site.setRetryTimes(2);
  29. return site;
  30. }
  31. }

4. 文章去重工具类

TestNlp

  1. package com.md.demo.nlp.test;
  2. import org.nlpcn.commons.lang.finger.FingerprintService;
  3. import org.nlpcn.commons.lang.finger.SimHashService;
  4. /**
  5. * 指纹去重库Github地址:https://github.com/hemin1003/nlp-lang
  6. *
  7. * 更多阅读:https://blog.csdn.net/hemin1003/article/details/82819489(【应用算法】信息流-推荐系统的去重策略)
  8. *
  9. * @author Minbo
  10. */
  11. public class TestNlp {
  12. /**
  13. * 任何一段信息文字,都可以对应一个不太长的随机数,作为区别它和其它信息的指纹(Fingerprint)。
  14. * 只要算法设计的好,任何两段信息的指纹都很难重复,就如同人类的指纹一样。信息指纹在加密、信息压缩和处理中有着广泛的应用。
  15. * 这里的做法是文章抽取特征词,压缩为md5指纹。利用这些指纹进行hash去重。广泛应用在搜索结果、推荐结果去重。
  16. */
  17. public static void main(String[] args) {
  18. String content = "卓尔防线继续伤筋动骨 队长梅方出场再补漏说起来卓尔队长梅方本赛季就是个“补漏”的命!在中卫与右边后卫间不停地轮换。如果不出意外,今天与广州恒大一战梅方又要换位置,这也是汉军队长连续三场比赛中的第三次换位。而从梅方的身上也可以看出,本赛季汉军防线如此“折腾”,丢球多也不奇怪了。梅方自2009赛季中乙出道便一直司职中后卫,还曾入选过布拉泽维奇国奥队,也是司职的中卫。上赛季,梅方与忻峰搭档双中卫帮助武汉卓尔队中超成功,但谁知进入本赛季后从第一场比赛开始梅方便不断因为种种“意外”而居无定所。联赛首战江苏舜天时,也是由于登贝莱受伤,朱挺位置前移,梅方临危受命客串右边后卫。第二轮主场与北京国安之战梅方仅仅打了一场中卫,又因为柯钊受罚停赛4轮而不得不再次到边路“补漏”。随着马丁诺维奇被弃用,梅方一度成为中卫首选,在与上海东亚队比赛中,邱添一停赛,梅方与忻峰再度携手,紧接着与申鑫队比赛中移至边路,本轮忻峰又停赛,梅方和邱添一成为中卫线上最后的选择。至于左右边后卫位置,卓尔队方面人选较多,罗毅、周恒、刘尚坤等人均可出战。记者马万勇原标题:卓尔防线继续伤筋动骨队长梅方出场再补漏稿源:中新网作者:";
  19. String content2 = "在中卫与右边后卫间不停地轮换。卓尔防线继续伤筋动骨 队长梅方出场再补漏说起来卓尔队长梅方本赛季就是个“补漏”的命!还曾入选过布拉泽维奇国奥队,也是司职的中卫。上赛季,梅方与忻峰搭档双中卫帮助武汉卓尔队中超成功,但谁知进入本赛季后从第一场比赛开始梅方便不断因为种种“意外”而居无定所。";
  20. // 方式1
  21. // String f1 = new FingerprintService().fingerprint(content);
  22. // String f2 = new FingerprintService().fingerprint(content2);
  23. // System.out.println(f1);
  24. // System.out.println(f2);
  25. // System.out.println(f1.equals(f2));
  26. // 方式2
  27. SimHashService service = new SimHashService();
  28. String f3 = String.valueOf(service.fingerprint(content));
  29. String f4 = String.valueOf(service.fingerprint(content2));
  30. System.out.println(f3);
  31. System.out.println(f4);
  32. System.out.println(f3.equals(f4));
  33. // System.out.println(service.hmDistance(content, content2));
  34. }
  35. }

更多阅读:【应用算法】信息流-推荐系统的去重策略

5. 计划任务

ScheduledTasks:

  1. package com.md.demo.task;
  2. import org.springframework.scheduling.annotation.Scheduled;
  3. import org.springframework.stereotype.Component;
  4. import com.md.demo.crawler.test.MyPageProcessor;
  5. import lombok.extern.slf4j.Slf4j;
  6. import us.codecraft.webmagic.Spider;
  7. @Component
  8. @Slf4j
  9. public class ScheduledTasks {
  10. /**
  11. * 每30秒执行一次
  12. */
  13. @Scheduled(initialDelay = 5000, fixedDelay = 30000)
  14. public void httTaskOfWechatPay() {
  15. log.info("------------------------------------------------");
  16. log.info("============爬虫数据任务,start===================");
  17. // TODO 在这里,你可以把爬虫做成执行计划任务,或者动态执行计划(通过db配置,或quartz框架,或XXL-job任务调度计划框架)
  18. log.info("开始爬虫数据...");
  19. log.info("处理处理...可以入库db,或存入es中");
  20. // 爬今日头条/热点数据url
  21. Spider.create(new MyPageProcessor()).addUrl(
  22. "https://m.toutiao.com/list/?tag=news_hot&ac=wap&count=20&format=json_raw&as=A1551E75BC4CF9C&cp=5E5C3CEFB9DCAE1&max_behot_time=1583123351&_signature=CXZIuwAAVy.txcPhjSEcTwl2SK&i=1583123351")
  23. .thread(1).run();
  24. log.info("爬虫结束...done");
  25. log.info("============爬虫数据任务,end===================");
  26. log.info("------------------------------------------------");
  27. }
  28. }

注:可以改写成多线程模式,并发抓取多个tag分类的新闻数据,但频率不要很高,不然容易命中爬虫IP反作弊(可以加上ip代理)

6. 启动类

Application:

  1. package com.md.demo;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.scheduling.annotation.EnableScheduling;
  6. import org.springframework.web.cors.CorsConfiguration;
  7. import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
  8. import org.springframework.web.filter.CorsFilter;
  9. /**
  10. * 程序主入口
  11. *
  12. * @author Minbo
  13. *
  14. */
  15. @SpringBootApplication
  16. @EnableScheduling
  17. public class Application {
  18. public static void main(String[] args) {
  19. SpringApplication.run(Application.class, args);
  20. }
  21. /**
  22. * 开启过滤器功能
  23. *
  24. * @return
  25. */
  26. private CorsConfiguration buildConfig() {
  27. CorsConfiguration corsConfiguration = new CorsConfiguration();
  28. corsConfiguration.addAllowedOrigin("*");
  29. corsConfiguration.addAllowedHeader("*");
  30. corsConfiguration.addAllowedMethod("*");
  31. return corsConfiguration;
  32. }
  33. /**
  34. * 跨域过滤器
  35. *
  36. * @return
  37. */
  38. @Bean
  39. public CorsFilter corsFilter() {
  40. UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
  41. source.registerCorsConfiguration("/**", buildConfig());
  42. return new CorsFilter(source);
  43. }
  44. }

完整源码下载

我的Github源码地址:

https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler

下一章教程

SpringBoot从入门到精通教程(三十二)- MybatisPlus框架动态数据源用法(支持多个DB,动态切换数据源)

该系列教程

SpringBoot从入门到精通教程

 

我的专栏

 

 

至此,全部介绍就结束了

 

 

-------------------------------

-------------------------------

 

我的CSDN主页

关于我(个人域名)

我的开源项目集Github

 

期望和大家一起学习,一起成长,共勉,O(∩_∩)O谢谢

欢迎交流问题,可加个人QQ 469580884,

或者,加我的群号 751925591,一起探讨交流问题

不讲虚的,只做实干家

Talk is cheap,show me the code

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/473877
推荐阅读
相关标签
  

闽ICP备14008679号