• Java爬虫的使用案例及简单总结


    通过三个简单的案例,来实现的,都是不加验证的情况下. 如果有拼图验证网上也有对应的实现方法自行查找即可. 这里仅仅是一个简单的Demo, 练习使用

    0. 爬取网站的配置:
    article:
      config:
        #中央新闻网-三农头条数据部分
        ntvUrl: https://www.ntv.cn/
        # 全国农技推广网- 农技动态部分
        nongJi: https://www.natesc.org.cn/dtxx/index?CategoryId=959cd01c-e9fa-43d9-a04b-48317bdc3794
        # 农技网基础路径
        nongJiBaseUrl: https://www.natesc.org.cn
        # 中国农网-热点推荐数据
        farmerUrl: https://www.farmer.com.cn/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    1. 依赖导入
    
    <dependency>
        <groupId>org.jsoupgroupId>
        <artifactId>jsoupartifactId>
        <version>1.13.1version>
    dependency>
    
    <dependency>
        <groupId>net.sourceforge.htmlunitgroupId>
        <artifactId>htmlunitartifactId>
        <version>2.43.0version>
    dependency>
    
    <dependency>
        <groupId>commons-iogroupId>
        <artifactId>commons-ioartifactId>
        <version>2.11.0version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    2. 配置类
    package com.saas.prod.common;
    
    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;
    
    /**
     * @author : Cookie
     * date : 2023/11/15
     */
    @Component
    @Data
    // prefix 中的配置只能是小写,否则编译过不去好像
    @ConfigurationProperties(prefix = "article.config")
    public class ArticleMessageConfig {
    
        /**
         * 中央新闻网 三农头条数据url
         */
        private String ntvUrl;
    
        /**
         * 农技中心动态
         */
        private String nongJi;
    
        /**
         * 农技基础url
         */
        private String nongJiBaseUrl;
    
        /**
         * 中国农网url
         */
        private String farmerUrl;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    中央新闻网-三农动态部分
    @Override
        public void insertNtvData() {
            String url = messageConfig.getNtvUrl();
            String html = HttpClientUtil.doGetForHTML(url);
            Document document = Jsoup.parse(html);
            Elements elements = document.getElementsByClass("question_rank");
            Elements aElements = elements.get(0).select("a");
            for (Element aElement : aElements) {
                String href = aElement.attr("href");
                String title = aElement.getElementsByTag("p").attr("title");
                ArticleMessage build = ArticleMessage.builder()
                        .title(title)
                        .insertTime(LocalDateTime.now())
                        .build();
                if (getHref(href, build))
                    break;
            }
        }
    
        /**
         * 三农头条数据填充
         *
         * @param url   路径
         * @param build 对象
         */
        private boolean getHref(String url, ArticleMessage build) {
            String html = HttpClientUtil.doGetForHTML(url);
            Document document = Jsoup.parse(html);
            Elements article = document.select("div.art_con");
            Elements select = document.select("p.mb10");
            String source = select.select("span").get(0).text();
            String createTime = select.select("span").get(1).text();
            build.setSource(source);
            build.setTime(createTime.split(" ")[0]);
            build.setArticle(article.toString().replace("
    ", "
    ")); String todayStartStr = getTodayStartStr(); // 如果是当天的新闻再插入到数据库,因为旧数据都已经插入了也就没有必要执行了 if (todayStartStr.compareTo(build.getTime()) <= 0) { if (0 == articleMessageMapper.selectByTitle(build.getTitle())) articleMessageMapper.insert(build); } else { // 说明剩余的数据都是旧数据,就不在操作直接返回 return true; } return false; }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    中国农网-热点推荐数据
    @Override
        public void insertFarmerData() {
            Document parse = Jsoup.parse(HttpClientUtil.doGetForHTML(messageConfig.getFarmerUrl()));
            Elements elements = parse.getElementsByClass("area-center w-486");
            Elements a = elements.select("a");
            for (Element element : a) {
                String href = element.attr("href");
                String title = element.text();
                ArticleMessage build = ArticleMessage.builder()
                        .title(title)
                        .build();
                if (setMessageForFarmer(href, build))
                    break;
            }
        }
    
    /**
         * 中国农网获取数据填充
         *
         * @param href  链接
         * @param build 数据对象
         */
        private boolean setMessageForFarmer(String href, ArticleMessage build) {
            try {
                Document parse = Jsoup.parse(HttpClientUtil.doGetForHTML(href));
                Elements elementsByClass = parse.getElementsByClass("index-introduce");
                Elements elements = elementsByClass.select("li");
                String source = elements.first().select("span").text();
                String date = elementsByClass.select("ul").first().select("div").first().select("span").text();
    
                Elements article = parse.getElementsByClass("textList");
                build.setSource(source);
                build.setTime(date.split(" ")[0]);
                build.setInsertTime(LocalDateTime.now());
                build.setArticle(article.toString().replace("
    ", "
    ")); String todayStartStr = getTodayStartStr(); // 如果是当天的新闻再插入到数据库,因为旧数据都已经插入了也就没有必要执行了 if (todayStartStr.compareTo(build.getTime()) <= 0) { if (0 == articleMessageMapper.selectByTitle(build.getTitle())) articleMessageMapper.insert(build); } else { return true; } } catch (Exception e) { // 这里有异常的及时提醒我查找问题 MailUtils.sendMail("yfs1024@163.com", "数据插入异常", "路径:" + href); log.error("数据插入异常:{},路径{}", e.getMessage(), href); return true; } return false; }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    全国农技推广网- 农技动态部分
        @Override
        public void insertNongJiData() {
            Document document1 = getParsedDocument(messageConfig.getNongJi());
            if (document1 == null)
                return;
            Element newsUl = document1.getElementById("newsUl");
            Elements elements = newsUl.select("a");
            for (Element element : elements) {
                String href = element.attr("href");
                String title = element.attr("title");
                String finalUrl = messageConfig.getNongJiBaseUrl() + href;
                ArticleMessage build = ArticleMessage.builder()
                        .title(title)
                        .build();
                // 填充其他数据
                if (setMessageForNongji(build, finalUrl))
                    break;
            }
        }
    
        /**
         * 填充农技动态中心数据
         *
         * @param build    对象
         * @param finalUrl 路径
         */
        private boolean setMessageForNongji(ArticleMessage build, String finalUrl) {
            try {
                Document parsedDocument = getParsedDocument(finalUrl);
                if (parsedDocument == null)
                    return true;
                Element newsTime = parsedDocument.getElementById("newsTime");
                Elements elements = newsTime.getElementsByClass("span1");
                String date = elements.first().getElementsByClass("span2").text();
                String source = elements.get(1).getElementsByClass("span2").text();
                Element content = parsedDocument.getElementById("content");
                String finalContent = content.toString().replace("src=\"", "src=\"" + messageConfig.getNongJiBaseUrl());
                build.setTime(date);
                build.setSource(source);
                build.setInsertTime(LocalDateTime.now());
                // 填充文本数据包括图片
                build.setArticle(finalContent);
                String todayStartStr = getTodayStartStr();
                // 插入当天的
                if (todayStartStr.compareTo(date) <= 0) {
                    if (0 == articleMessageMapper.selectByTitle(build.getTitle()))
                        articleMessageMapper.insert(build);
                } else {
                    // 说明剩余的数据都是旧数据,就不在操作直接返回
                    return true;
                }
            } catch (Exception e) {
                MailUtils.sendMail("yfs1024@163.com", "数据插入异常", "路径:" + finalUrl);
                log.error("数据插入异常:{},路径{}", e.getMessage(), finalUrl);
            }
            return false;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    示例HTML:
    <div class="index-introduce">
      <ul>
        <li>来源:
          <span>中国农网span>
        li>
        <li>编辑:
          <span>暴佳然span>
        li>
        <li>作者:
          <span>杨志华span>
        li>
        <div>
          <span>2023-11-17 08:45:11span>
        div>
      ul>
      <div class="fontSize">
        <img class="add" src="https://www.farmer.com.cn//Public/newNongWang/images/字体变大.png?time=657" alt="">
        <img class="sub" src="https://www.farmer.com.cn//Public/newNongWang/images/字体减小.png?time=277" alt="">
      div>
    div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    Document parse = Jsoup.parse(HttpClientUtil.doGetForHTML(href));
    // 通过class获取节点
    Elements elementsByClass = parse.getElementsByClass("index-introduce");
    // 获取节点中所有的li标签数据
    Elements elements = elementsByClass.select("li");
    // 获取第一个li中的span标签中的文本内容  也就是这里的: 中国农网
    String source = elements.first().select("span").text();
    // 获取ul标签,再获取ul中的div获取span中的文本
    String date = elementsByClass.select("ul").first().select("div").first().select("span").text();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    方法总结:

    获取标签的常用方法
    getElementsByClass
    // 通过class定位
    Elements elementsByClass = parse.getElementsByClass("index-introduce");
    
    • 1
    • 2
    getElementsById
    // 通过id定位
    Element newsTime = parsedDocument.getElementById("newsTime");
    
    • 1
    • 2
    select

    这里方法有很多选择方式,详细在最下面的链接中

    通过Element对象获取对应的标签

    getElementsByTag

    通过标签获取

    String title = aElement.getElementsByTag("p").attr("title");
    
    • 1
    获取属性常用方法
    attr
    String href = element.attr("href");
    String title = element.attr("title");
    
    • 1
    • 2
    总结:
    1. 通过HttpClient获取到界面的html
    2. 通过JSoup进行解析, 获得一个Document对象
    3. 通过方法一层一层的获取到其中的数据,或者属性

    其他的常用方法链接:

    jsoup使用指南

  • 相关阅读:
    oracle后台进程详解#进程结构
    盲人餐厅点餐:科技之光照亮餐桌上的美食之旅
    基于SpringBoot的校园点餐系统
    在SpringBoot框架下,接口有读个实现类,在不改变任何源码的情况下,SpringBoot怎么知道给接口注入哪个实现类的依赖呢?
    hive集群加了个参数后,union all的任务都执行不了影响业务
    每日三题 9.06
    快速了解jwt
    虚拟现实(VR)游戏与增强现实(AR)游戏的区别
    NX二次开发-挂菜单栏.men和工具条.rtb及菜单中文汉字乱码问题
    1476_OSP以及HASL等几种PCB表面处理工艺了解
  • 原文地址:https://blog.csdn.net/qq_47910339/article/details/134460953