WebMagic爬虫框架(爬取前程无忧网站的招聘信息保存到mysql数据库)

梦里梦外; 2023-06-07 08:05 75阅读 0赞

爬取前程无忧的网站招聘信息保存到mysql数据库

  • 一,WebMagic的四大组件
  • 二,用于数据流转的对象
  • 三,项目开始前的热身(解析页面的方式)
  • 四,SpringBoot项目环境搭建
  • 五,配置文件
  • 六,Let’s go WebMagic!
    • 1,启动类
    • 2,实体类(存储到数据库表的字段)
    • 3,爬虫类
    • 4,获取爬到的数据并保存到数据库
    • 5,dao和service
  • 七,后话

WebMagic框架包含四个组件, PageProcessorSchedulerDownloaderPipeline
这四大组件对应爬虫生命周期中的处理、管理、下载和持久化等功能。
这四个组件都是 Spider中的属性,爬虫框架通过 Spider启动和管理。
WebMagic总体架构图
在这里插入图片描述

一,WebMagic的四大组件

PageProcessor负责解析页面,抽取有用信息,以及发现新的链接。需要自己定义。
Scheduler负责管理待抓取的URL,以及一些去重的工作。一般无需自己定制Scheduler。
Pipeline负责抽取结果的处理,包括计算、持久化到文件、数据库等。
Downloader负责从互联网上下载页面,以便后续处理。一般无需自己实现。

二,用于数据流转的对象

Request 是对URL地址的一层封装,一个Request对应一个URL地址。
Page代表了从Downloader下载到的一个页面——可能是HTML,也可能是JSON或者其他文本格式的内容。
ResultItems相当于一个Map,它保存PageProcessor处理的结果,供Pipeline使用。

三,项目开始前的热身(解析页面的方式)

项目maven添加了下面要求的maven坐标之后就可以写下面的测试代码了。
下面的测试很清楚的讲解了解析页面的方式,以及爬虫的执行。

  • page.putField()是把爬取到的数据添加到了ResultItems中,默认在控制台打印出来。

    public class JobProcessor implements PageProcessor {

    1. //解析页面
    2. public void process(Page page) {
    3. //解析返回的数据page,并且把解析的结果放在resultItems中
    4. //css选择器解析
    5. //page.putField("爬取内容",page.getHtml().css("span.service_txt").all());//all()是返回所有数据,get()是返回第一条数据
    6. //XPath解析
    7. //page.putField("xpath方法解析结果",page.getHtml().xpath("//div[@id=J_cate]/ul/li/a").all());
    8. //正则表达式解析(筛选内容带“装”字的所有信息)
    9. page.putField("正则",page.getHtml().css("div#J_cate ul li a").regex(".*装.*").all());
    10. //获取链接

    // page.addTargetRequests(page.getHtml().css(“div#shortcut-2014 div.w ul.fl li#ttbar-home a”).links().all());
    // page.putField(“url”,page.getHtml().css(“div#shortcut div ul li a span”).all());

    1. }
    2. private Site site=Site.me()
    3. .setCharset("utf8") //设置编码
    4. .setTimeOut(10000) //设置超时时间 单位是ms毫秒
    5. .setRetrySleepTime(3000) //设置重试的时间间隔
    6. .setSleepTime(3); //设置重试次数
    7. public Site getSite() {
    8. return site;
    9. }

    /设置request请求方式 Request requests=new Request(“http://www.12371.cn/cxsm/gzbs/“); requests.setMethod(HttpConstant.Method.GET); Spider.create(new JobProcessor()) //.addUrl(url) .addRequest(requests) .setScheduler(new QueueScheduler().setDuplicateRemover(new BloomFilterDuplicateRemover(100000))) .thread(5) .addPipeline(this.newsData) .run(); /

    1. //主函数,执行爬虫
    2. public static void main(String[] args) {
    3. Spider spider=Spider.create(new JobProcessor()).addUrl("https://www.jd.com")//设置爬取数据的页面

    // .addPipeline(new FilePipeline(“D:\result”))//使用Pipeline保存数据到指定文件夹中,自动生成文件

    1. .thread(5) //多线程进行爬取,5个多线程,速度更快
    2. .setScheduler(new QueueScheduler().setDuplicateRemover(new BloomFilterDuplicateRemover(10000000)));//设置布隆去重过滤器,指定最多对1000万数据进行去重操作
    3. //默认HashSet去重
    4. //Scheduler scheduler=spider.getScheduler();
    5. spider.run();//run()执行爬虫
    6. }

    }

四,SpringBoot项目环境搭建

首先搭建好一个springboot项目,加入mysqlmybatiswebmagic的核心依赖以及扩展依赖,以及添加WebMagic对布隆过滤器的支持的依赖。

  1. <!--springmvc-->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. <version>2.1.3.RELEASE</version>
  6. </dependency>
  7. <!--mysql-->
  8. <dependency>
  9. <groupId>mysql</groupId>
  10. <artifactId>mysql-connector-java</artifactId>
  11. <version>8.0.13</version>
  12. </dependency>
  13. <!--mybatis-->
  14. <dependency>
  15. <groupId>org.mybatis</groupId>
  16. <artifactId>mybatis</artifactId>
  17. <version>3.4.6</version>
  18. </dependency>
  19. <dependency>
  20. <groupId>org.mybatis.spring.boot</groupId>
  21. <artifactId>mybatis-spring-boot-starter</artifactId>
  22. <version>2.0.1</version>
  23. </dependency>
  24. <dependency>
  25. <groupId>us.codecraft</groupId>
  26. <artifactId>webmagic-core</artifactId>
  27. <version>0.7.3</version>
  28. <exclusions>
  29. <exclusion>
  30. <groupId>org.slf4j</groupId>
  31. <artifactId>slf4j-log4j12</artifactId>
  32. </exclusion>
  33. </exclusions>
  34. </dependency>
  35. <dependency>
  36. <groupId>us.codecraft</groupId>
  37. <artifactId>webmagic-extension</artifactId>
  38. <version>0.7.3</version>
  39. </dependency>
  40. <!--WebMagic对布隆过滤器的支持-->
  41. <dependency>
  42. <groupId>com.google.guava</groupId>
  43. <artifactId>guava</artifactId>
  44. <version>16.0</version>
  45. </dependency>
  46. <!--工具包 StringUtils-->
  47. <dependency>
  48. <groupId>org.apache.commons</groupId>
  49. <artifactId>commons-lang3</artifactId>
  50. <version>3.9</version>
  51. </dependency>

五,配置文件

resources文件夹新建log4j.properties文件配置日志

  1. log4j.rootLogger=INFO,A1 log4j.appender.A1=org.apache.log4j.ConsoleAppender log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=%-d{ yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n

在新建application.properties文件配置数据库

  1. spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
  2. spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC
  3. spring.datasource.username=root
  4. spring.datasource.password=1234

六,Let’s go WebMagic!

1,启动类

  1. @SpringBootApplication
  2. @MapperScan("com.qianlong.dao") //扫描mapper文件
  3. @EnableScheduling //开启定时任务,定时抓取数据
  4. @ComponentScan(value = "com.qianlong")//包扫描
  5. public class App {
  6. public static void main(String[] args) {
  7. SpringApplication.run(App.class,args);
  8. }
  9. }

2,实体类(存储到数据库表的字段)

  1. public class JobInfo {
  2. private Integer id;
  3. private String companyName;
  4. private String companyAddr;
  5. private String companyInfo;
  6. private String jobName;
  7. private String jobAddr;
  8. private String salary;
  9. private String time;
  10. }

3,爬虫类

  1. package com.qianlong.task;
  2. import com.qianlong.entity.JobInfo;
  3. import org.jsoup.Jsoup;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.scheduling.annotation.Scheduled;
  6. import org.springframework.stereotype.Component;
  7. import us.codecraft.webmagic.Page;
  8. import us.codecraft.webmagic.Site;
  9. import us.codecraft.webmagic.Spider;
  10. import us.codecraft.webmagic.processor.PageProcessor;
  11. import us.codecraft.webmagic.scheduler.BloomFilterDuplicateRemover;
  12. import us.codecraft.webmagic.scheduler.QueueScheduler;
  13. import us.codecraft.webmagic.selector.Html;
  14. import us.codecraft.webmagic.selector.Selectable;
  15. import java.util.List;
  16. @Component
  17. public class JobProcessor implements PageProcessor {
  18. //前程无忧网站的职位列表地址
  19. private String url="https://search.51job.com/list/170200,000000,0000,00,9,99,%2B,2,1.html?lang=c&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=";
  20. @Override
  21. public void process(Page page) {
  22. //解析页面,获取招聘信息详情的url地址
  23. List<Selectable> list = page.getHtml().css("div#resultList div.el").nodes();
  24. //判断集合是否为空
  25. if(list.size()==0){
  26. //如果为空,表示这是招聘详情页,解析页面,获取招聘详情信息,保存数据
  27. this.saveJobInfo(page);
  28. }else {
  29. //如果不为空,表示这是列表页,解析出详情页的url地址,放到任务队列中
  30. for(Selectable selectable:list){
  31. String jobInfoUrl = selectable.links().toString();
  32. //把获取到的详情页的url地址放到任务队列中
  33. page.addTargetRequest(jobInfoUrl);
  34. }
  35. //获取下一页按钮的url
  36. String bkUrl=page.getHtml().css("div.p_in li.bk").nodes().get(1).links().toString();//get(1)拿到第二个
  37. //把下一页的url放到任务队列中
  38. page.addTargetRequest(bkUrl);
  39. }
  40. }
  41. //解析页面,获取招聘详情信息,保存数据
  42. private void saveJobInfo(Page page) {
  43. //创建招聘详情对象
  44. JobInfo jobInfo=new JobInfo();
  45. //拿到解析的页面
  46. Html html = page.getHtml();
  47. //获取数据,封装到对象中
  48. //两种获取的方法,一种是直接html.css,另一种是使用Jsoup.parse解析html字符串
  49. jobInfo.setCompanyName(html.css("div.cn p.cname a","text").toString());
  50. String addrStr = Jsoup.parse(html.css("div.cn p.msg").toString()).text();
  51. String addr=addrStr.substring(0,addrStr.indexOf("|"));
  52. jobInfo.setCompanyAddr(addr);
  53. jobInfo.setCompanyInfo(html.css("div.tmsg","text").toString());
  54. jobInfo.setUrl(page.getUrl().toString());
  55. jobInfo.setJobName(Jsoup.parse(html.css("div.cn h1","title").toString()).text());
  56. jobInfo.setJobAddr(addr);
  57. jobInfo.setSalary(Jsoup.parse(html.css("div.cn strong").toString()).text());
  58. //把结果保存起来
  59. page.putField("jobInfo",jobInfo);
  60. }
  61. private Site site=Site.me()
  62. .setCharset("gbk")//设置编码(页面是什么编码就设置成什么编码格式的)
  63. .setTimeOut(10*1000)//设置超时时间
  64. .setRetrySleepTime(3000)//设置重试的间隔时间
  65. .setRetryTimes(3);//设置重试的次数
  66. @Override
  67. public Site getSite() {
  68. return site;
  69. }
  70. //这里注入SaveData
  71. @Autowired
  72. private SaveData saveData;
  73. //initialDelay当任务启动后,等多久执行方法
  74. //fixedDelay每个多久执行方法
  75. @Scheduled(initialDelay = 1000,fixedDelay = 100*1000)
  76. public void process(){
  77. Spider.create(new JobProcessor())
  78. .addUrl(url)
  79. .setScheduler(new QueueScheduler().setDuplicateRemover(new BloomFilterDuplicateRemover(100000)))
  80. .thread(10)
  81. .addPipeline(this.saveData)//指定把爬取的数据保存到SaveData类的ResultItems中
  82. .run();
  83. }
  84. }

4,获取爬到的数据并保存到数据库

前面爬取的数据(封装到了实体类)都保存在了ResultItems对象中
在这里插入图片描述
这里取出前面保存的数据(实体类),然后把数据存到数据库

  1. package com.qianlong.task;
  2. import com.qianlong.entity.JobInfo;
  3. import com.qianlong.service.Service;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.stereotype.Component;
  6. import us.codecraft.webmagic.ResultItems;
  7. import us.codecraft.webmagic.Task;
  8. import us.codecraft.webmagic.pipeline.Pipeline;
  9. @Component
  10. public class SaveData implements Pipeline {
  11. @Autowired
  12. Service service;
  13. @Override
  14. public void process(ResultItems resultItems, Task task) {
  15. //获取封装好的招聘详情对象
  16. JobInfo jobInfo=resultItems.get("jobInfo");
  17. if(jobInfo!=null){
  18. //保存数据到数据库中
  19. service.saveJobInfo(jobInfo);
  20. }
  21. }
  22. }

5,dao和service

  1. public interface Dao {
  2. @Insert(value = "insert into jobinfo(companyName,companyAddr,companyInfo,jobName,jobAddr,salary,url) values(#{companyName},#{companyAddr},#{companyInfo},#{jobName},#{jobAddr},#{salary},#{url});")
  3. int saveJobInfo(JobInfo jobInfo);
  4. }
  5. public interface Service {
  6. int saveJobInfo(JobInfo jobInfo);
  7. }
  8. @Service
  9. public class ServiceImpl implements Service {
  10. @Autowired
  11. private Dao dao;
  12. @Override
  13. public int saveJobInfo(JobInfo jobInfo) {
  14. int i = dao.saveJobInfo(jobInfo);
  15. return i;
  16. }
  17. }

然后运行启动类,控制台出现下图就是爬取成功了
在这里插入图片描述
爬取的数据保存到数据库成功
在这里插入图片描述

七,后话

至于WebMagic的完整使用,还需要涉及到代理服务器,因为有一些网站是禁止爬取的,它会查到你的ip地址并给你禁掉,所以这时就需要代理服务器。以及爬取数据的去重问题,还要借助一些其他的工具平台进行处理整合,所以,有待完善。
在这里插入图片描述
每天进步一点点,有问题留言兄弟盟!

发表评论

表情:
评论列表 (有 0 条评论,75人围观)

还没有评论,来说两句吧...

相关阅读