博客文章质量分数列表【分页、排序、搜索】

news2024/10/7 20:33:29

文章目录

  • 一、分析
  • 二、代码
    • 1、前端代码
    • 2、后端代码
  • 三、实现效果
  • 四、总结
    • 1、出现安全验证
    • 2、401 Unauthorized: [no body]

一、分析

官方提供的质量分查询入口:CSDN质量分
输入我们要查的文章即可,比如:https://blog.csdn.net/qq_36433289/article/details/132909403?spm=1001.2014.3001.5502
在这里插入图片描述

请求接口:https://bizapi.csdn.net/trends/api/v1/get-article-score
请求参数:https://blog.csdn.net/qq_36433289/article/details/132909403?spm=1001.2014.3001.5502
返回参数:

{
    "code": 200,
    "message": "success",
    "data": {
        "article_id": "132909403",
        "score": 93,
        "message": "文章质量良好",
        "post_time": "2023-09-18 20:42:24"
    }
}

所以,只要我们得到我们的所有文章链接,然后遍历请求https://bizapi.csdn.net/trends/api/v1/get-article-score,组装结果就行

二、代码

1、前端代码

个人博客质量分查看页面

<!doctype html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>博文质量分批量查询</title>

    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdn.bootcdn.net/ajax/libs/bootstrap-icons/1.10.4/font/bootstrap-icons.min.css" rel="stylesheet">
    <link href="https://cdn.bootcdn.net/ajax/libs/bootstrap-table/1.21.4/bootstrap-table.min.css" rel="stylesheet">

</head>
<body>

    <div class="container pt-5">
        <div class="mt-5">
            <form class="row justify-content-md-center">
                <div class="col-6">
                    <div class="input-group">
                        <input class="form-control form-control-lg" type="text" id="username" value="qq_36433289" placeholder="请输入用户ID">
                        <button class="btn btn-outline-secondary" type="button" onclick="searchScore()">批量查询</button>
                    </div>
                </div>
            </form>

            <div id="articleScore" class="mt-5">
                <div id="toolbar">
                    <button type="button" class="btn btn-primary">
                        100~90 <span class="badge text-bg-secondary">0</span>
                    </button>
                    <button type="button" class="btn btn-info">
                        89~80 <span class="badge text-bg-secondary">0</span>
                    </button>
                    <button type="button" class="btn btn-success">
                        79~70 <span class="badge text-bg-secondary">0</span>
                    </button>
                    <button type="button" class="btn btn-warning">
                        69~60 <span class="badge text-bg-secondary">0</span>
                    </button>
                    <button type="button" class="btn btn-danger">
                        60以下 <span class="badge text-bg-secondary">0</span>
                    </button>
                </div>
                <table id="table"
                       data-toolbar="#toolbar"
                       data-locale="zh-CN"
                       data-url="allArticleScore"
                       data-show-columns="true"
                       data-pagination="true"
                       data-search="true"
                       data-show-export="true"
                       data-show-refresh="true"
                       data-show-fullscreen="true"
                       data-show-toggle="true">
                    <thead>
                    <tr>
                        <th data-field="articleId">文章ID</th>
                        <th data-field="title" data-formatter="titleFormatter">标题</th>
                        <th data-field="postTime" data-sortable="true">发布时间</th>
                        <th data-field="viewCount" data-sortable="true">浏览量</th>
                        <th data-field="score" data-sortable="true" data-cell-style="scoreCellStyle">质量分</th>
                        <th data-field="message">提示信息</th>
                    </tr>
                    </thead>
                </table>
            </div>
        </div>
    </div>

    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/js/bootstrap.bundle.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/bootstrap-table/1.21.4/bootstrap-table.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/bootstrap-table/1.21.4/locale/bootstrap-table-zh-CN.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/xlsx/0.18.5/xlsx.core.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/jspdf/2.5.1/polyfills.umd.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/TableExport/5.2.0/js/tableexport.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/bootstrap-table/1.21.4/extensions/export/bootstrap-table-export.min.js"></script>

    <script>
        $(document).ready(function() {
            // 初始化表格
            $("#table").bootstrapTable({
                onLoadSuccess: function (data) {
                    // 统计各分数段文章数量
                    let levelArray = [0, 0, 0, 0, 0];
                    $.each(data.rows, function(index, value) {
                        if (value.score >= 90){
                            levelArray[0]++;
                        } else if(value.score < 90 && value.score >= 80){
                            levelArray[1]++;
                        } else if(value.score < 80 && value.score >= 70 ){
                            levelArray[2]++;
                        } else if(value.score < 70 && value.score >= 60){
                            levelArray[3]++;
                        } else if (value.score < 60) {
                            levelArray[4]++;
                        }
                    });

                    // 统计数量展示
                    let levelSpanArray = $("#toolbar > button >span");
                    $.each(levelSpanArray, function (index, value) {
                        $(value).text(levelArray[index]);
                    });
                }
            });
        });

        // 查询文章质量分
        function searchScore(){
            $("#table").bootstrapTable("refresh", {url: 'http://127.0.0.1:8880/ceshi/allArticleScore?username=' + $("#username").val()});
        }

        // 文章标题格式化
        function titleFormatter(value, row, index){
            return `<a href="${row.url}" target="_blank">${value}</a>`;
        }

        // 单元格样式,根据分数段设置背景颜色
        function scoreCellStyle(value, row, index){
            let c = "";
            if (value >= 90){
                c = "bg-primary";
            } else if(value < 90 && value >= 80){
                c = "bg-info";
            } else if(value < 80 && value >= 70 ){
                c = "bg-success"
            } else if(value < 70 && value >= 60){
                c = "bg-warning";
            } else if (value < 60) {
                c = "bg-danger";
            }

            return {classes : c};
        }
    </script>
</body>
</html>

注:http://127.0.0.1:8880/ceshi/allArticleScore?username=需要替换你的接口

2、后端代码

业务接口

public interface IArticleService {
	ArrayList<LinkedHashMap<String, Object>> getArticleScoreList(String username);
}

业务详细实现代码

@Service
public class ArticleServiceImpl implements IArticleService {

    @Autowired
    private RestTemplateArticle restTemplateArticle;

    /**
     * 获取所有文章质量分列表
     *
     * @param username 用户ID
     * @return ArrayList<LinkedHashMap<String, Object>> 文章质量分数
     */
    @Override
    public ArrayList<LinkedHashMap<String, Object>> getArticleScoreList(String username) {

        ArrayList<LinkedHashMap<String, Object>> articleScoreList = new ArrayList<>();

        // 判断传入的用户ID不为空
        if (username != null && !"".equals(username)){
            // 查询用户下文章总数
            int blogTotal = (int) restTemplateArticle.getTabTotal(username).get("blog");

            // 判断文章总数
            if (blogTotal > 0){
                // 查询用户下所有文章
                ArrayList<LinkedHashMap<String, Object>> blogList  = restTemplateArticle.getBusinessBlogList(username, blogTotal);

                // 判断获取的文章列表数量
                if (blogList.size() > 0){
                    // 查询文章质量分
                    articleScoreList = restTemplateArticle.getArticleScore(blogList);
                }
            }
        }
        return articleScoreList;
    }
}

一共需要请求3个接口,具体封装如下:

@Component
public class RestTemplateArticle {

    private static final String CA_KEY = "xxx1";
    private static final String CA_Nonce = "xxx2";
    private static final String CA_Signature = "xxx3";
    
    @Autowired
    private RestTemplate restTemplate;
    
    /**
     * 根据用户ID获取博客Tab标签页统计数据
     *
     * @param username 用户ID
     * @return LinkedHashMap<String, Object> 标签页统计数量
     */
    public LinkedHashMap<String, Object> getTabTotal(String username) {

        LinkedHashMap<String, Object> linkedHashMap = new LinkedHashMap<>();

        // 远程请求url
        String url = "https://blog.csdn.net/community/home-api/v1/get-tab-total?username=" + username;

        try {
            // 使用RestTemplate发送GET请求并返回响应对象
            ResponseEntity<JSONObject> response = restTemplate.getForEntity(url, JSONObject.class);
            // 获取响应数据:data(返回数据项有 code、message、traceId、data)
            linkedHashMap = (LinkedHashMap<String, Object>) response.getBody().get("data");

        } catch (RestClientException e) {
            e.printStackTrace();
        }

        return linkedHashMap;
    }


    /**
     * 获取全部博文列表数据
     *
     * @param username 用户ID
     * @param total    文章总数,注意服务器每页最高可获取100条,在这里我们每页查询50条
     * @return ArrayList<LinkedHashMap < String, Object>> 文章列表数据
     */
    public ArrayList<LinkedHashMap<String, Object>> getBusinessBlogList(String username, int total) {

        ArrayList<LinkedHashMap<String, Object>> blogList = new ArrayList<>(total);

        // 计算页数:通过总数和每页展示数量
        int pageNum = total % 50 == 0 ? total / 50 : (total / 50) + 1;
        // 请求每页数据
        for (int i = 1; i <= pageNum; i++) {
            // 远程请求url,拼接参数:每页固定展示50条,需要拼接页数
            String url = "https://blog.csdn.net/community/home-api/v1/get-business-list?page=" + i + "&size=50&businessType=blog&orderby=&noMore=false&year=&month=&User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.69&username=" + username;

            try {
                // 使用RestTemplate发送GET请求并返回响应对象
                ResponseEntity<JSONObject> response = restTemplate.getForEntity(url, JSONObject.class);
                // 获取响应数据:data(返回数据项有 code、message、traceId、data)
                LinkedHashMap<String, Object> dataMap = (LinkedHashMap<String, Object>) response.getBody().get("data");
                // 从data中获取文章列表数据
                blogList.addAll((ArrayList<LinkedHashMap<String, Object>>) dataMap.get("list"));

            } catch (RestClientException e) {
                e.printStackTrace();
            }
        }

        return blogList;
    }

    /**
     * 获取文章质量分数
     *
     * @param blogList 文章列表
     * @return ArrayList<LinkedHashMap < String, Object>> 文章质量分(文章信息+质量分信息)
     */
    public ArrayList<LinkedHashMap<String, Object>> getArticleScore(ArrayList<LinkedHashMap<String, Object>> blogList) {

        ArrayList<LinkedHashMap<String, Object>> scoreList = new ArrayList<>(blogList.size());

        // 远程请求url
        String url = "https://bizapi.csdn.net/trends/api/v1/get-article-score";

        // 设置请求头信息,以下为必须项
        HttpHeaders headers = new HttpHeaders();
        headers.set("Accept", "application/json, text/plain, */*");
        headers.set("X-Ca-Key", CA_KEY);
        headers.set("X-Ca-Nonce", CA_Nonce);
        headers.set("X-Ca-Signature", CA_Signature);
        headers.set("X-Ca-Signature-Headers", "x-ca-key,x-ca-nonce");
        headers.set("X-Ca-Signed-Content-Type", "multipart/form-data");
        // 设置媒体类型
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);

        // 循环远程请求查询所有文章质量分数
        for (LinkedHashMap<String, Object> blog : blogList) {
            // 设置请求报头和正文
            MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
            requestBody.put("url", Collections.singletonList((String) blog.get("url")));
            HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);

            // 创建请求URI
            URI uri = URI.create(url);

            try {
                // 使用RestTemplate发送POST请求并返回响应对象
                ResponseEntity<JSONObject> response = restTemplate.postForEntity(uri, requestEntity, JSONObject.class);
                // 获取响应数据:data(返回数据项有 code、message、traceId、data)
                LinkedHashMap<String, Object> dataMap = (LinkedHashMap<String, Object>) response.getBody().get("data");
                // 将文章数据和质量分合并
                dataMap.putAll(blog);
                // 将单篇质量分数信息添加到list集合中
                scoreList.add(dataMap);

            } catch (RestClientException e) {
                e.printStackTrace();
            }
        }
        return scoreList;
    }

    
}

其中, CA_KEY = "xxx1";CA_Nonce = "xxx2";CA_Signature = "xxx3";需要替换你自己博客的,具体可以随便打开一个页面,然后F12查看,具体如下:
在这里插入图片描述
对外暴露的接口

@RestController
public class ArticleController {

    @Autowired
    private IArticleService articleService;

    /**
     * 查询所有文章质量分数
     *
     * @param username 用户ID
     * @return
     */
    @GetMapping("/allArticleScore")
    public JSONObject allArticleScore(String username){
        // 获取所有文章质量分列表
        ArrayList<LinkedHashMap<String, Object>> articleScoreList = articleService.getArticleScoreList(username);

        // 封装查询结果,前端分页要求:rows、total
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("rows", articleScoreList);
        jsonObject.put("total", articleScoreList.size());

        return jsonObject;
    }
}

三、实现效果

在这里插入图片描述

四、总结

1、出现安全验证

获取获取全部博文列表数据,请求getBusinessBlogList出现以下异常

<head>
  <meta charset="utf-8">
  <title>请进行安全验证</title>
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta content="width=device-width, initial-sc... (2383 bytes)]
	at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:123)
	at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63)
	at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:782)
	at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:740)
	at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:674)
	at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:342)

直接访问链接出现以下情况
在这里插入图片描述
我们可以在页面通过安全验证,得到返回的参数如下:
在这里插入图片描述
然后在代码中手动组装我们的参数

String jsonString = "data.list里面的参数";
ObjectMapper objectMapper = new ObjectMapper();
                ArrayList<LinkedHashMap<String, Object>> blogList  = objectMapper.readValue(jsonString, new TypeReference<ArrayList<LinkedHashMap<String, Object>>>() {});

2、401 Unauthorized: [no body]

确保这几个参数CA_KEY = “xxx1”;CA_Nonce = “xxx2”;CA_Signature = "xxx3"替换为正确的

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

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

相关文章

开发板——X210开发板的SD卡启动方式

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 参考博客&#xff1a; S5PV210 SD卡启动 - 简书 关于存储器的相关基础知识&#xff0c;见博文&#xff1a; 外存——SD卡/iNand芯片与S5PV210的SD/MMC/iNand控制器-CSDN博客 RAM、ROM和FLASH三…

了解WPF控件:TreeView常用属性与用法(十五)

引言 TreeView控件是WPF&#xff08;Windows Presentation Foundation&#xff09;中用于显示分层数据的常用控件。这个控件允许用户以树形结构展示数据&#xff0c;使得数据更加清晰易懂。在创建文件浏览器、组织结构图等应用程序时&#xff0c;TreeView控件非常有用。 Tree…

R语言入门笔记2.0

1.创建数据框 在R语言中&#xff0c;可以使用data.frame函数来创建数据框。以下是一个简单的示例&#xff0c;这段R语言代码创建了一个名为student的数据框&#xff0c;其中包含了学生的ID、性别、姓名和出生日期&#xff0c;首先创建一个包含学生出生日期的向量&#xff0c;再…

探秘本庄村果园预售系统的技术之旅

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

【MCAL】TC397+EB-tresos之GPT配置实战 - 定时器

本篇文章介绍了在TC397平台使用EB-tresos对GPT驱动模块进行配置的实战过程,不仅介绍了使用GTM来实现定时器的方案&#xff0c;还介绍了基于GPT12来实现连续定时器的实例。因为GTM是德国博世公司开发的IP&#xff0c;而英飞凌的芯片集成了这个IP&#xff0c;并在这个基础上搭建了…

Pytest 与allure测试报告集成

通过Feature, story, step 记录测试的功能&#xff0c;场景及测试步骤 # login.pylogin_func函数 传入参数是name 和 password 当输入的name和password与数据库db_data中数据一致时&#xff0c;返回“XXX成功登录系统&#xff01;” 当输入的name存在于数据库db_data但密码不正…

双非本科准备秋招(13.1)—— 力扣 栈、队列与堆

1、103. 二叉树的锯齿形层序遍历 昨天做的二叉树的层序遍历&#xff0c;把代码直接拿过来。 这个题要求的是一个Z型遍历&#xff0c;如下图。 用一个变量f记录正反顺序&#xff0c;然后使用LinkedList记录答案&#xff0c;下图可以看到LinkedList继承了Deque&#xff0c;所以…

【知识图谱--第一讲概论】

深度学习–连接主义 知识图谱–符号主义 表示 有属性图和RDF图两种 RDF由三元组表示&#xff1a;Subject - Predicate - Object 存储 图数据库 抽取 融合 推理 问答 图算法

Linux:进程信号的概念与产生原理

文章目录 信号的概念实践信号关于前台和后台进程的操作 操作系统与外设信号的产生signal系统调用 前面的篇章结束了信号量的话题&#xff0c;那么接下来引入的是信号的话题&#xff0c;信号和信号量之间没有任何关系&#xff0c;只是名字比较像 信号的概念 在生活中存在各种各…

linux麒麟系统安装mongodb7.0

1.mogedb下载 下载的是他tar包 https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-7.0.5.tgz wget -o https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-7.0.5.tgz 也可以下载rpm包 2.将包上传至服务器并解压 #进入目录 并解压 cd /opt/ tar…

Linux ---- Shell编程之免交互

一、Here Document 多行重定向 1、Here Document定义 使用I/O重定向的方式将命令列表提供给交互式程序标准输入的一种替代品Here Document 是标准输 入的一种替代品&#xff0c;可以帮助脚本开发人员不必使用临时文件来构建输入信息&#xff0c;而是直接就地生产出一个文件…

技术科普 | 机器视觉5大关键技术及其常见应用

计算机视觉是指&#xff1a;让机器通过数字图像或视频等视觉信息来模拟人类视觉的过程&#xff0c;以达到对物体的理解、识别、分类、跟踪、重建等目的的技术。它是人工智能领域中的一个分支&#xff0c;涉及图像处理、模式识别、机器学习、深度学习等多个领域。 随着人工智能和…

7.2、子集求和问题与背包密码系统

7.2、子集求和问题与背包密码系统 一、数学描述 1.1、第一种描述 20 世纪 70 年代末&#xff0c;默克尔和赫尔曼首次尝试将密码系统建立在一个 NP-完全问题上。他们使用了以下数学问题的一个版本&#xff0c;该问题是对经典knapsack问题的概括。 子集和问题 假设你有一个正…

数据结构——链式二叉树(3)

本篇文章我们依然讲解链式二叉树的OJ题&#xff1b; 一、二叉树的层序遍历 层序遍历即从根节点开始一层一层的遍历。我们可以运用队列的先进先出特性实现&#xff01; //层序遍历 void a(BTNode* root) {Que qhead;Queueinit(&qhead);//先入队根节点if(root)QueuePush(&…

C#,计算几何,随机点集之三角剖分的德劳内(Delaunay)算法的源代码

一、三角剖分Delaunay算法简介 点集的三角剖分&#xff08;Triangulation&#xff09;&#xff0c;对数值分析&#xff08;比如有限元分析&#xff09;以及图形学来说&#xff0c;都是极为重要的一项预处理技术。尤其是Delaunay三角剖分&#xff0c;由于其独特性&#xff0c;关…

LeetCode: 160.相交链表(令人赞叹的优雅)

160. 相交链表 - 力扣&#xff08;LeetCode&#xff09; 目录 官方双指针解法&#xff1a; 博主的辣眼代码&#xff1a; 每日一表情包&#xff1a; 博主还未学习哈希表&#xff0c;所以介绍的是双指针法&#xff0c;此题的哈希表解法时O&#xff08;nm&#xff09;空O&…

MySQL窗口函数--lead()函数

lead()函数&#xff1a; 查询当前行向下偏移n行对应的结果 该函数有三个参数&#xff1a;第一个为待查询的参数列名&#xff0c;第二个为向下偏移的位数&#xff0c;第三个参数为超出最下面边界的默认值。 如下代码&#xff1a; 查询向下偏移 2 位的年龄 SELECT user_id,user…

JavaScript高级:深浅拷贝

目录 1 引言 2 浅拷贝 2.1 拷贝数组 1.2 拷贝对象 3 赋值操作和浅拷贝的比较 4 深拷贝 4.1 前置知识 --> 递归函数 4.2 使用递归实现深拷贝 4.3 js库中的lodash里面的cloneDeep内部实现深拷贝 4.4 利用JSON实现深拷贝 深浅拷贝只针对引用数据类型 1 引言 假如我们…

leetcode 19 , 118

19 .删除链表倒数第n个节点 思路1&#xff1a; 我首先想到的就是使用两个loop来进行解决&#xff1a; 遍历所有节点&#xff0c;得到需要删除节点的位置。再遍历一边所有节点&#xff0c;找到需要删除节点进行删除。 解决方案1&#xff1a; class Solution {public ListNod…

DevOps落地笔记-07|案例分析:如何有效管理第三方组件

上一讲主要介绍了如何通过代码预检查的方式提高入库代码的质量&#xff0c;将代码检查尽可能前置&#xff0c;降低修复问题的成本&#xff0c;从而提高交付软件的质量。除了代码本身的问题&#xff0c;依赖组件也是经常困扰开发者的一个问题。比如&#xff0c;依赖组件的某个版…