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

文章目录

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

一、分析

官方提供的质量分查询入口:CSDN质量分
输入我们要查的文章即可,比如:https://blog.csdn.net/qq_36433289/article/details/132909403?spm=1001.2014.3001.5502
博客文章质量分数列表【分页、排序、搜索】_第1张图片

请求接口: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">0span>
                    button>
                    <button type="button" class="btn btn-info">
                        89~80 <span class="badge text-bg-secondary">0span>
                    button>
                    <button type="button" class="btn btn-success">
                        79~70 <span class="badge text-bg-secondary">0span>
                    button>
                    <button type="button" class="btn btn-warning">
                        69~60 <span class="badge text-bg-secondary">0span>
                    button>
                    <button type="button" class="btn btn-danger">
                        60以下 <span class="badge text-bg-secondary">0span>
                    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">文章IDth>
                        <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 `${row.url}" target="_blank">${value}`;
        }

        // 单元格样式,根据分数段设置背景颜色
        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> 文章质量分数
     */
    @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 标签页统计数量
     */
    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> 文章列表数据
     */
    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> 文章质量分(文章信息+质量分信息)
     */
    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;
    }
}

三、实现效果

博客文章质量分数列表【分页、排序、搜索】_第2张图片

四、总结

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)

直接访问链接出现以下情况
博客文章质量分数列表【分页、排序、搜索】_第3张图片
我们可以在页面通过安全验证,得到返回的参数如下:
博客文章质量分数列表【分页、排序、搜索】_第4张图片
然后在代码中手动组装我们的参数

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"替换为正确的

你可能感兴趣的:(Java,java)