聚合平台项目之数据抓取

news2024/11/23 1:16:06

首先先记录一下我自己对这个数据抓取的一些心得:

数据抓取也就是常说的爬虫。

在我没真正去做的时候,我还想爬虫好高大上。

现在学完之后也就怯魅了

其实本质就是在自己的代码中模拟浏览器给后端发请求,后端收到响应之后,返回给前端,这个时候我们进行接收即可。

当然我说的那是最简单的数据抓取,如果别人网站有反爬虫的机制,那可能就需要更多的成本了

说完了心得之后,就开始真正记录了

首先分析的是数据抓取的流程:

    数据抓取流程

  1. 分析数据源,怎么获取?
  2. 拿到数据后,怎么处理?
  3. 写入数据库等存储

数据抓取的几种方式

  1. 直接请求数据接口(最方便),可使用 HttpClient、OKHttp、RestTemplate、Hutool 等客户端发送请求
  2. 等网页渲染出明文内容后,从前端完整页面中解析出需要的内容
  3. 有一些网站可能是动态请求的,他不会一次性加载所有的数据,而是要你点某个按钮、输入某个验证码才会显示出数据。可使用无头浏览器:selenium、node.js puppeteer(这篇文章没用到第三种方式)

获取网页的文字信息:

上面说了,本质上就是向后端发送请求

所以,我们第一步就是要知道往哪发请求,并且携带什么参数?

以编程导航网站为例编程导航 - 程序员一站式编程学习交流社区,做您编程学习路上的导航员 (code-nav.cn)

 

F12就能知道

查看这个携带的参数的时候,最好变成这种源代码模式,用视图好像是会有格式上的错误。

我们复制之后:

@SpringBootTest
public class crawler {

    @Resource
    private PostService postService;

    @Test
    public void TestCrawler(){
        String json ="{\"pageSize\":12,\"sortOrder\":\"descend\",\"tags\":[\"Java\"],\"current\":1,\"reviewStatus\":1,\"category\":\"文章\",\"hiddenContent\":true,\"priorityList\":[999,9999],\"sorterList\":[{\"field\":\"priority\",\"asc\":false},{\"field\":\"createTime\",\"asc\":false}]}";
        String url  = "https://api.code-nav.cn/api/course/list/page/vo";
        String result = HttpRequest.post(url)
                .body(json)
                .execute().body();
        Map<String,Object> map = JSONUtil.toBean(result,Map.class);
        JSONObject data = (JSONObject)map.get("data");
        JSONArray records = (JSONArray) data.get("records");
        //1:title 2:content 3:tag
        List<Post> postList = new ArrayList<>();
        for (Object record : records) {
            JSONObject tempjson = (JSONObject)record;
            Post post = new Post();
            post.setTitle(tempjson.getStr("title"));
            post.setContent(tempjson.getStr("content"));
            Object tags = tempjson.get("tags");
            if(!(tags instanceof JSONNull)){
                JSONArray jsonArray = (JSONArray) tempjson.get("tags");
                List<String> tagList = jsonArray.toList(String.class);
                post.setTags(JSONUtil.toJsonStr(tagList));
            }else {
                post.setTags("");
            }
            post.setUserId(1L);
            postList.add(post);
        }
        final boolean save = postService.saveBatch(postList);
        System.out.println(save);
    }

}

上面是编写了一个测试类。

一开始发送请求的时候,我们可以先看一下拿到了那些东西

到这一步,我们就需要思考?

我们需要什么?再针对从获得的资源中去取

我们项目的背景是要往数据库里面插入文章数据

所以我们需要的就是三个元素:

标题title    内容content    标签tags

明白了需求之后,我们就可以一步一步拆解我们拿到的资源

然后我们发现拿到的东西是一个json格式的数据

同样也是用Hutool的JSON解析的工具转换。

获取网页的图片信息:

在说获取网页的图片信息之前

可以先说一下这个项目的搜索图片的原理

这个平台搜索图片并不是将所有图片都存储在自己的数据库中

是自己的前端访问我的后端

然后我的后端通过我自己代码的逻辑去访问其它人的服务器

整体流程就是这样

讲完这个,我们直接开始

在开始看代码和网页之前,需要先介绍一个工具:Jsoup解析库:支持发送请求获取HTML文档,并且从中解析出需要的字段。

第一步肯定也是导入依赖:

        <!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.15.3</version>
        </dependency>

第二步访问官网然后获取实例代码

jsoup: Java HTML parser, built for HTML editing, cleaning, scraping, and XSS safety

Document doc = Jsoup.connect("https://en.wikipedia.org/").get();
log(doc.title());
Elements newsHeadlines = doc.select("#mp-itn b a");
for (Element headline : newsHeadlines) {
  log("%s\n\t%s", 
    headline.attr("title"), headline.absUrl("href"));
}
  1. 连接到 Wikipedia 并获取 HTML 文档

    Document doc = Jsoup.connect("https://en.wikipedia.org/").get();

    • Jsoup.connect("https://en.wikipedia.org/"):使用 Jsoup 连接到指定的 URL(在这里是 Wikipedia 的主页)。
    • .get():发送 HTTP GET 请求以获取该 URL 的 HTML 内容,并将其解析为 Document 对象。
  2. 记录网页标题

    log(doc.title());

    • doc.title():获取网页的标题。
    • log(...):假设这是一个自定义方法或库函数,用于打印或记录信息。这里它会输出网页的标题。
  3. 选择特定的 HTML 元素

    Elements newsHeadlines = doc.select("#mp-itn b a"); 
    • doc.select("#mp-itn b a"):使用 CSS 选择器从 HTML 文档中选择所有符合 #mp-itn b a 选择器的元素。
    • Elements 是一个 Jsoup 的集合类,包含了所有符合选择器的 Element 对象。
  4. 遍历并记录每个新闻标题的标题属性和链接

    for (Element headline : newsHeadlines) { log("%s\n\t%s", headline.attr("title"), headline.absUrl("href")); }

    • for (Element headline : newsHeadlines):遍历所有选择器匹配到的 Element 对象。
    • headline.attr("title"):获取当前 Elementtitle 属性,这通常是链接的悬浮提示文本。
    • headline.absUrl("href"):获取当前 Elementhref 属性的绝对 URL。
    • log("%s\n\t%s", ...):记录或打印出每个新闻标题的 title 属性和 href 链接的绝对 URL。

总的来说,这段代码从 Wikipedia 的主页抓取 "In the news" 区域的所有新闻链接,然后输出每条新闻的标题和链接。

这里有一个点就是这个css选择器,待会也得需要用到这个点。

讲完了步骤

我们下面开始从网页分析:

当我们找不到页面中图片的元素的时候可以点这个检查

然后我们上下找一找

就会发现

这个class叫iusc的css样式选择器,就包含这个图片

然后我们复制这个名字

然后我们鼠标往上一放,就会发现所有的图片都被选中了

ok,那我们图片的资源就找到了

下一个是对应这个图片的标题

这个什么inflnk就能跟踪到这个图片的文字

我们还是和上面一样

最后整合一下,我们直接看代码:

@SpringBootTest
public class crawler {

    @Resource
    private PostService postService;

   
    @Test
    public void JsoupTest() throws IOException {
        String current = "1";
        String url = "https://cn.bing.com/images/search?q=小黑子&form=HDRSC2&first="+current;
        Document doc = Jsoup.connect(url).get();
        Elements elements = doc.select(".iusc");
        final Elements elements1 = doc.select("a.inflnk");
        List<Picture> pictureList = new ArrayList<>();
        for (int i = 0; i < elements.size(); i++) {
            //获取图片
            final String m = elements.get(i).attr("m");
            Map<String,Object> map = JSONUtil.toBean(m,Map.class);
            final String murl = (String) map.get("murl");
            //获取标题
            final String title = elements1.get(i).attr("aria-label");
            Picture picture = new Picture();
            picture.setMurl(murl);
            picture.setTitle(title);
            pictureList.add(picture);
        }
    }

}

我们代码的整体逻辑就是:

首先先修改一下这个url

并且和上面Jsoup的select一样,我们将这个图片中我们刚刚获取的这个css样式选择器直接cv上去

接着就可以获取这个返回值了

然后我们也是一步一步进行输出,每个网页包裹的东西不太一样,我们一层一层取出来就行。

最后稍微来看一下在项目中的实现:

首先就是这个文字资源

我将这个这个放到了一个一次性任务中

这个一次性任务怎么保证一次性呢

我们都知道springboot项目启动后会加载所有的bean对象

我们只需要将这个类注册成bean即可,然后用完直接把@Component注销掉即可

下一个是图片的项目实战应用

@Service
public class PictureDataSource implements DataSource{
    @Override
    public Page doSearch(String searchText, long pageNum, long pageSize) {
        String url = String.format("https://cn.bing.com/images/search?q=%s&form=HDRSC2&first=%s",searchText,pageSize);
        Document doc = null;
        try {
            doc = Jsoup.connect(url).get();
        } catch (IOException e) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR);
        }
        Elements elements = doc.select(".iusc");
        final Elements elements1 = doc.select("a.inflnk");
        List<Picture> pictureList = new ArrayList<>();
        for (int i = 0; i < elements.size(); i++) {
            //获取图片
            final String m = elements.get(i).attr("m");
            Map<String,Object> map = JSONUtil.toBean(m,Map.class);
            final String murl = (String) map.get("murl");
            //获取标题
            final String title = elements1.get(i).attr("aria-label");
            Picture picture = new Picture();
            picture.setMurl(murl);
            picture.setTitle(title);
            pictureList.add(picture);
            if(pictureList.size()>=pageSize){
                break;
            }
        }
        Page<Picture> picturePage= new Page<>(pageNum,pageSize);
        picturePage.setRecords(pictureList);
        return picturePage;
    }
}

整体的东西是差不多的

我们将这个url修改成动态了

之前在测试类中我们是写死了小黑子

这里用一个searchText就行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2036626.html

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

相关文章

Redis知识进阶-私人定制组

Redis 目录 RedisRedis 简介关键特征Redis不同操作系统安装在Linux上的安装&#xff1a;在macOS上的安装&#xff1a;在Windows上的安装&#xff1a; Redis 数据结构及特点常用5种及示例&#xff1a;其他结构 主要功能总结 Redis 简介 Redis是一个开源的高性能键值对数据库&am…

酶促4+2和2+2环加成反应(有机合成与生物合成)-文献精读38

酶促42和22环加成反应&#xff1a;区域与立体选择性的理解与应用 01 有机合成 类似有机化学&#xff1a;狄尔斯–阿尔德反应 狄尔斯–阿尔德反应是[42]环加成反应中最具代表的&#xff0c;由共轭双烯与亲双烯体构建环己烯骨架的经典反应。反应有良好的立体、位置选择性。 该…

3.类和对象(中)

1. 类的默认成员函数 默认成员函数就是用户没有显式实现&#xff0c;编译器会自动生成的成员函数称为默认成员函数&#xff08;就是我们不写&#xff0c;编译器会默认生成一份&#xff09;。一个类&#xff0c;我们不写的情况下编译器会默认生成以下6个默认成员函数&#xff0…

江协科技STM32学习笔记(第09章 I2C通信)

第09章 I2C通信 9.1 I2C通信协议 9.1.1 I2C通信 串口通信没有时钟线的异步全双工的协议。 案例&#xff1a;通信协议设计&#xff1a; 某个公司开发了一款芯片&#xff0c;可以干很多事情,比如AD转换、温湿度测量、姿态测量等等。这个芯片里的众多外设也是通过读写寄存器来…

InCDE论文翻译

InCDE论文翻译 Towards Continual Knowledge Graph Embedding via Incremental Distillation 通过增量蒸馏实现持续知识图嵌入 Abstract 传统的知识图嵌入(KGE)方法通常需要在新知识出现时保留整个知识图(KG)&#xff0c;这会带来巨大的训练成本。为了解决这个问题&#xf…

掌握网络数据的钥匙:Python Requests-HTML库深度解析

文章目录 掌握网络数据的钥匙&#xff1a;Python Requests-HTML库深度解析背景&#xff1a;为何选择Requests-HTML&#xff1f;什么是Requests-HTML&#xff1f;如何安装Requests-HTML&#xff1f;5个简单库函数的使用方法3个场景下库的使用示例常见Bug及解决方案总结 掌握网络…

[C++][opencv]基于opencv实现photoshop算法可选颜色调整

【测试环境】 vs2019 opencv4.8.0 【效果演示】 【核心实现代码】 SelectiveColor.hpp #ifndef OPENCV2_PS_SELECTIVECOLOR_HPP_ #define OPENCV2_PS_SELECTIVECOLOR_HPP_#include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" #include "…

笔记:在WPF中OverridesDefaultStyle属性如何使用

一、目的&#xff1a;介绍下在WPF中OverridesDefaultStyle属性如何使用 OverridesDefaultStyle 属性在 WPF 中用于控制控件是否使用默认的主题样式。将其设置为 True 时&#xff0c;控件将不会应用默认的主题样式&#xff0c;而是完全依赖于你在 Style 中定义的样式。以下是如何…

代码随想录算法训练营day39||动态规划07:多重背包+打家劫舍

多重背包理论 描述&#xff1a; 有N种物品和一个容量为V 的背包。 第i种物品最多有Mi件可用&#xff0c;每件耗费的空间是Ci &#xff0c;价值是Wi 。 求解将哪些物品装入背包可使这些物品的耗费的空间 总和不超过背包容量&#xff0c;且价值总和最大。 本质&#xff1a; …

图论------迪杰斯特拉(Dijkstra)算法求单源最短路径。

编程要求 在图的应用中&#xff0c;有一个很重要的需求&#xff1a;我们需要知道从某一个点开始&#xff0c;到其他所有点的最短路径。这其中&#xff0c;Dijkstra 算法是典型的最短路径算法。 本关的编程任务是补全右侧代码片段中 Begin 至 End 中间的代码&#xff0c;实现 …

543 二叉树的直径

解题思路&#xff1a; \qquad 如果某一个点&#xff08;非叶子节点&#xff09;在最长路径上&#xff0c;那么应该有两种情况&#xff1a; \qquad 情况一&#xff1a;该节点为非转折点&#xff0c;最长路径经过其一个子节点 父节点&#xff1b; \qquad 情况二&#xff1a;该…

Rancher 使用 Minio 备份 Longhorn 数据卷

0. 概述 Longhorn 支持备份到 NFS 或者 S3, 而 MinIO 就是符合 S3 的对象存储服务。通过 docker 部署 minio 服务&#xff0c;然后在 Longhorn UI 中配置备份服务即可。 1. MinIO 部署 1.1 创建备份目录 mkdir -p /home/longhorn-backup/minio/data mkdir -p /home/longhor…

24经济师报名照上传技巧,无需下载照片工具

24经济师报名照上传技巧&#xff0c;无需下载照片工具 #中级经济师 #经济师 #高级经济师 #经济师报名照片 #中级经济师报名照片 #经济师考试

SPI通讯协议示例

目录 0x01 SPI通讯特点0x01 硬件SPI示例0x02 软件SPI示例 0x01 SPI通讯特点 SPI在接线方面会拥有片选引脚、时钟引脚、数据引脚&#xff0c;其中数据引脚又分为 MISO和MOSI&#xff0c;分别对应的是 “Master IN Slave Out”(主机输入从机输出) 和 “Master Out Slave IN”(主…

机械学习—零基础学习日志(如何理解线性代数)

零基础为了学人工智能&#xff0c;正在快乐学习&#xff0c;每天都长脑子 如何理解线性代数&#xff1f; 线性代数的本质是代数——代替数字。有时数学里有很多的规律&#xff0c;不以数字形式存在&#xff0c;可以用字幕替代。用一个通用的等式替代我们发现的规律。 代数研…

在VB.net中,CDbl、Double.Parse与Double.TryParse有什么区别

标题 在VB.net中&#xff0c;CDbl、Double.Parse与Double.TryParse有什么区别 正文 在VB.NET中&#xff0c;CDbl、Double.Parse和Double.TryParse都是用于将不同类型的值&#xff08;主要是字符串&#xff09;转换为Double类型的方法&#xff0c;但它们之间在用法、性能、错误处…

django学习入门系列之第七点《案例 添加页面》

文章目录 7.6 前端整合标准引入格式案例 添加页面 往期回顾 7.6 前端整合 HTMLCSSjavaScript、jQueryBootStrap&#xff08;动态效果依赖于jQuery&#xff09; 标准引入格式 css在上面js动态效果放下面bootstrap依赖于jQuery&#xff0c;所以先要有jQuery&#xff0c;再有bo…

汽车精密设计、无人机外形优化总是遇难题?CFD参数优化详解2来袭

数值仿真的参数优化 在上期文章中&#xff0c;我们给大家带来了机翼多学科优化、拟合试验曲线、一维CFD模型参数的DOE和回归分析三个参数优化案例&#xff0c;本期文章将继续为各位讲解多个 Altair CFD 参数优化案例&#xff0c;一起来看看吧。 案例&#xff1a;汽车排气管形状…

Jenkins链接Gitlab(HttpSSH方式)

文章目录 前言一、安装必要插件1、安装git2、安装Jenkins插件 二、配置git1、http方式&#xff08;1&#xff09;基础配置&#xff08;http方式配置凭证&#xff09;&#xff08;2&#xff09;测试 2、SSH方式配置凭证 总结 前言 为避免汉化导致的显示差异&#xff0c;以下操作…

通过Go示例理解函数式编程思维

一个孩子要尝试10次、20次才肯接受一种新的食物&#xff0c;我们接受一种新的范式&#xff0c;大概不会比这个简单。-- 郭晓刚 《函数式编程思维》译者 函数式编程(Functional Programming, 简称fp)是一种编程范式&#xff0c;与命令式编程(Imperative Programming)、面向对象编…