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;
}
中央新闻网-三农动态部分
@Overridepublic 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;}
中国农网-热点推荐数据
@Overridepublic 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;}
全国农技推广网- 农技动态部分
    @Overridepublic 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.mzph.cn/news/151826.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

elasticsearch 概述

初识elasticsearch 了解ES elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎&#xff0c;具备非常多强大功能&#xff0c;可以帮助我们从海量数据中快速找到需要的内容 例如&#xff1a; 在GitHub搜索代码 在电商网站搜索商品 ELK技术栈 elasticsearc…

简述如何使用Androidstudio对文件进行保存和获取文件中的数据

在 Android Studio 中&#xff0c;可以使用以下方法对文件进行保存和获取文件中的数据&#xff1a; 保存文件&#xff1a; 创建一个 File 对象&#xff0c;指定要保存的文件路径和文件名。使用 FileOutputStream 类创建一个文件输出流对象。将需要保存的数据写入文件输出流中…

Vue3的异步组件使用

通过defineAsyncComponent引入组件&#xff0c;使用Suspense渲染 Suspense有两个插槽&#xff0c;一个default一个fallback <template><Suspense><template #default><userCard></userCard></template><template #fallback>加载中…

我叫:插入排序【JAVA】

1.自我介绍 插入式排序属于内部排序法,是对于欲排序的元素以插入的方式找寻该元素的适当位置&#xff0c;以达到排序的目的。 2.继承我的思想 插入排序(Insertion Sorting)的基本思想是:把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包…

WPF ObservableCollection 和 BindingList 有什么区别

ObservableCollection<T>和BindingList<T>都是.NET Framework中的泛型集合类型&#xff0c;它们都支持数据绑定和元素的增加、删除、修改等操作。然而&#xff0c;它们之间存在一些关键的差异&#xff0c;使它们在不同的场景下更有用。 ObservableCollection: Ob…

C#的MessagePack(unity)--02

高级API (MessagePackSerializer) MessagePackSerializer类是MessagePack for C# 的入口点。静态方法构成了MessagePack for C# 的主要API。 APIDescriptionSerialize<T>将一个对象图序列化为MessagePack二进制块。可以使用异步变体获取Stream。也有非泛型重载可用。De…

设计模式—结构型模式之外观模式(门面模式)

设计模式—结构型模式之外观模式&#xff08;门面模式&#xff09; 外观&#xff08;Facade&#xff09;模式又叫作门面模式&#xff0c;是一种通过为多个复杂的子系统提供一个一致的接口&#xff0c;而使这些子系统更加容易被访问的模式。 例子 我们的电脑会有很多 组件&am…

动态页面调研及设计方案

文章目录 vue2 动态表单、动态页面调研一、form-generator二、ng-form-element三、Variant Form四、form-create vue2 动态表单、动态页面调研 一、form-generator 预览&#xff1a;https://mrhj.gitee.io/form-generator/#/ Vue2 Element UI支持拖拽生成表单不支持其他组件…

反电动势对电机起动过程电流的影响

参考链接&#xff1a;反电动势对电机起动过程电流的影响 - 知乎

一个关于proto 文件的经验分享 :gRPC 跨语言双端通信显示错误码:12 UNIMPLEMENTED (附赠gRPC错误码表)

错误现象描述&#xff1a; 在使用c的客户端向golang的服务端发送远程调用时&#xff0c;显示&#xff1a; /home/zry/gRPC/grpc-v1.45.2/examples/cpp/DeviceData/greeter_client.cc83 12: unknown service DeviceData.DeviceDataService Greeter 接收到: RPC 失败这里的unkn…

pytorch的backward()的底层实现逻辑

自动微分是一种计算张量&#xff08;tensors&#xff09;的梯度&#xff08;gradients&#xff09;的技术&#xff0c;它在深度学习中非常有用。自动微分的基本思想是&#xff1a; 自动微分会记录数据&#xff08;张量&#xff09;和所有执行的操作&#xff08;以及产生的新张…

基于梯度算法优化概率神经网络PNN的分类预测 - 附代码

基于梯度算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于梯度算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于梯度优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络的光滑…

细说MySQL数据类型

TOC 目录 MySQL数据类型 数据类型分类 数值类型 tinyint类型 有符号tinyint范围测试 无符号tinyint范围测试 bit类型 bit类型的显示方式 bit类型的范围测试 float类型 有符号float范围测试 无符号float范围测试 decimal类型 字符串类型 char类型 char类型测试 …

Ubuntu 18.04/20.04 LTS 操作系统设置静态DNS

1、nano /etc/systemd/resolved.conf 2、修改配置 使用DNS服务器&#xff1a;223.5.5.5 223.6.6.6 [Resolve] DNS223.5.5.5 223.6.6.6 3、重启服务 systemctl restart systemd-resolved.service 4、查看解析文件 cat /run/systemd/resolve/resolv.conf # This file is man…

Jmeter 如何监控目标服务的系统资源

下载Jmeter插件管理下载 perfmon 将这个插件管理放到Jmeter的\lib\ext目录下 然后重启Jmeter jmeter-plugins-manager-1.10.jar 下载 perfmon插件 添加 io 内存 磁盘的监听 并且添加监听 在宿主机中安装代理监听程序 并启动 ServerAgent.tar.gz

数据结构-插入排序

插入排序 插入排序的三种常见方法&#xff1a; 直接插入排序、折半插入排序、希尔排序。 数据存储结构 因为我们是用的是C语言来实现算法&#xff0c;因此我们需要创建一个结构体&#xff0c;用来存放初始数据。 结构体定义如下&#xff1a; #define MAX 100 typedef int…

设计原则 | 开放封闭原则

一、开放封闭原则&#xff08;OCP&#xff1a;Open-Closed Principle&#xff09; 1、原理 软件实体&#xff08;类、模块、函数等等&#xff09;应该是可以扩展的&#xff0c;但是不可修改的。如果程序中的一处改动就会引发连锁反应&#xff0c;导致一些列相关模块的修改&…

GPT实战系列-P-Tuning本地化训练ChatGLM2等LLM模型,到底做了什么?(二)

GPT实战系列-如何使用P-Tuning本地化训练ChatGLM2等LLM模型&#xff1f;(二) 文章目录 GPT实战系列-1.训练参数配置传递2.训练前准备3.训练参数配置4.训练对象&#xff0c;seq2seq训练5.执行训练6.训练模型评估依赖数据集的预处理 P-Tuning v2 将 ChatGLM2-6B 模型需要微调的参…

MATLAB 嵌套switch语句||MATLAB while循环

MATLAB 嵌套switch语句 在 MATLAB 中嵌套 switch 语句是可能的&#xff0c;可以在 switch 一部分外嵌套 switch 语句序列。即使 case 常量的内部和外部的 switch 含有共同的值&#xff0c;也不算冲突出现。 MATLAB嵌套switch语句语法 嵌套switch语句的语法如下&#xff1a; s…

012 C++ AVL_tree

前言 本文将会向你介绍AVL平衡二叉搜索树的实现 引入AVL树 二叉搜索树虽可以缩短查找的效率&#xff0c;但如果数据有序或接近有序普通的二叉搜索树将退化为单支树&#xff0c;查找元素相当于在顺序表中搜索元素&#xff0c;效率低下。因此&#xff0c;两位俄罗斯的数学家G.M…