当前位置: 首页 > article >正文

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. 依赖导入
<!-- 作用是把html界面封装为一个Document对象 类似于Python的 Beautiful Soup -->
<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.13.1</version>
</dependency>
<!-- 这个是处理未进行界面渲染的问题, 比如农机网的全国农技推广网-农技动态部分通过HTTPClient获取的就是未渲染的 -->
<dependency>
    <groupId>net.sourceforge.htmlunit</groupId>
    <artifactId>htmlunit</artifactId>
    <version>2.43.0</version>
</dependency>
<!-- 上面依赖这个jar包 -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
</dependency>
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;
}

中央新闻网-三农动态部分
@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("<div class=\"art_con\">", "<div id=\"content\">"));
        String todayStartStr = getTodayStartStr();
        // 如果是当天的新闻再插入到数据库,因为旧数据都已经插入了也就没有必要执行了
        if (todayStartStr.compareTo(build.getTime()) <= 0) {
            if (0 == articleMessageMapper.selectByTitle(build.getTitle()))
                articleMessageMapper.insert(build);
        } else {
            // 说明剩余的数据都是旧数据,就不在操作直接返回
            return true;
        }
        return false;
    }
中国农网-热点推荐数据
@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("<div class=\"textList\">", "<div id=\"content\">"));
            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;
    }
全国农技推广网- 农技动态部分
    @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;
    }
示例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:11</span>
    </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>
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();

方法总结:

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

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

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

getElementsByTag

通过标签获取

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

其他的常用方法链接:

jsoup使用指南


http://www.kler.cn/a/134983.html

相关文章:

  • 【软件工程】一篇入门UML建模图(类图)
  • 时间管理的三个痛点
  • 2411C++,C++26反射示例
  • uniapp+vue2 设置全局变量和全局方法 (兼容h5/微信小程序)
  • Java设计模式面试题及参考答案
  • 闯关leetcode——3174. Clear Digits
  • 场景交互与场景漫游-路径漫游(7)
  • 腾讯云轻量数据库性能如何?轻量数据库租用配置价格表
  • JavaScript实现飞机发射子弹详解(内含源码)
  • 超聚变服务器关闭超线程CPU的步骤(完整版)
  • 【开源】基于Vue.js的在线课程教学系统的设计和实现
  • 右键菜单和弹出菜单的区别
  • 基于springboot实现校园在线拍卖系统项目【项目源码】计算机毕业设计
  • 如何在Linux上搭建本地Docker Registry并实现远程连接
  • vscode 推送本地新项目到gitee
  • Linux入门(三)
  • 22. 深度学习 - 自动求导
  • 反射和序列化操作会破坏单例模式
  • redis 介绍1
  • three.js相机调用reset方法复原但无法完全复原
  • docker 部署Redis集群(三主三从,以及扩容、缩容)
  • flink的window和windowAll的区别
  • list转map(根据某个或多个属性分组)
  • 基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(六)
  • JAVA必应回答。
  • 参加了南京 GDG 活动:这些精彩的技术讨论,值得与你分享~