超实用!CSDN个人数据Chrome插件开发

插件简介

相信写过博客的都知道,每天会经常打开自己的主页无数次,尤其是写了一篇新文章,就为了看文章浏览量增长了多少,文章获得了多少个赞,有多少人评论(谁不想自己写的文章成为爆款呢~)

因此我特意做了一个Chrome插件,让用户更方便地实时查看自己在CSDN博客上的数据

我们先来看看最后的实现效果:

在这里插入图片描述

这个插件能显示两部分数据,一部分是用户个人数据,包括:总阅读数、文章数、排名、粉丝数,另一部分是个人博客成就数据,包括:点赞数、评论数、收藏数、分享数

插件显示的数据默认每1小时更新一次,用户可以自行修改数据更新时间

插件的UI第一版写的暂时比较简陋,可以后期版本再修改以及增加一些功能

在开发之前,我们需要会一些前置知识,包括:Node.js爬虫、Chrome插件开发

不会的同学也没关系,可以看我之前写过的博客,里面关于爬虫和插件开发写的非常详细:

都 2023 年了还不会 Node.js 爬虫?快学起来!

Node.js 爬虫只会 Cheerio?来试试 Puppeteer!

从零入门 Chrome 插件开发

好的,现在我们就来开动吧!

爬取CSDN个人数据

这里默认大家已经学过puppeteer,具体爬取的操作在上一篇文章中有很详细的解释

这里我们分析完网页结构之后直接来编写爬虫脚本:

// 无头浏览器模块
const puppeteer = require("puppeteer");

// 目标页面
const crawlPage = "https://blog.csdn.net/weixin_46232841?spm=1000.2115.3001.5343";

// 网页爬虫
async function crawler() {
    //创建实例
    const browser = await puppeteer.launch({
        //无浏览器界面启动
        headless: "new",
        //放慢浏览器执行速度,方便测试观察
        slowMo: 100,
        // 设置打开的浏览器窗口尺寸
        defaultViewport: { width: 960, height: 540 },
    });

    // 新开一个tab页面
    const page = await browser.newPage();
    // 加载目标页,在 500ms 内没有任何网络请求才算加载完
    await page.goto(crawlPage, { waitUntil: "networkidle0" });

    // 在无头浏览器页面dom环境,获取页面数据
    const myData = await page.evaluate(() => {
        let data = {};
        let name = "萌萌哒の瑞萌萌";
        let achievement = {};

        // 个人数据
        document.querySelectorAll(".user-profile-head-info-r-c ul").forEach((ele) => {
            const allReadNum = ele.querySelector("li:nth-child(1) .user-profile-statistics-views .user-profile-statistics-num").innerText;
            const articleNum = ele.querySelector("li:nth-child(2) .user-profile-statistics-num").innerText;
            const rank = ele.querySelector("li:nth-child(3) .user-profile-statistics-num").innerText;
            const fans = ele.querySelector("li:nth-child(4) .user-profile-statistics-num").innerText;
            data = {
                allReadNum,articleNum,rank,fans
            }
        });
        
        // 个人成就
        document.querySelectorAll(".aside-common-box-achievement").forEach((ele) => {
            const like = ele.querySelector("li:nth-child(1) div").innerText;
            const comment = ele.querySelector("li:nth-child(2) div").innerText;
            const favorite = ele.querySelector("li:nth-child(3) div").innerText;
            const share = ele.querySelector("li:nth-child(4) div").innerText;
            achievement = {
                like,comment,favorite,share
            }
        });
        return {
            name,data,achievement
        };
    });

    console.log(myData);

    // 关闭tab页
    await page.close();
    // 关闭实例
    await browser.close();
})

运行一下看看有没有获取到我们想要的数据吧:

在这里插入图片描述

完美!现在我们拿到了我们想要的数据,接下来要完成的需求就是:

  1. 将数据存储到json文件里,方便插件目录获取
  2. 定时爬取,每隔一小时爬取一次,及时更新json文件

解决办法:用 fs 模块的fs.writeFile来保存文件,用 node-schedule 模块来实现定时爬取

上代码!

// 无头浏览器模块
const puppeteer = require("puppeteer");
const schedule = require('node-schedule');
const fs = require('fs');

// 目标页面
const crawlPage = "https://blog.csdn.net/weixin_46232841?spm=1000.2115.3001.5343";

// 创建一个定时任务,每隔1小时执行一次
let job = schedule.scheduleJob('0 0 */1 * * *',// 网页爬虫
async function crawler() {
    //创建实例
    const browser = await puppeteer.launch({
        //无浏览器界面启动
        headless: "new",
        //放慢浏览器执行速度,方便测试观察
        slowMo: 100,
        // 设置打开的浏览器窗口尺寸
        defaultViewport: { width: 960, height: 540 },
    });

    // 新开一个tab页面
    const page = await browser.newPage();
    // 加载目标页,在 500ms 内没有任何网络请求才算加载完
    await page.goto(crawlPage, { waitUntil: "networkidle0" });

    // 在无头浏览器页面dom环境,获取页面数据
    const myData = await page.evaluate(() => {
        let data = {};
        let name = "萌萌哒の瑞萌萌";
        let achievement = {};

        // 个人数据
        document.querySelectorAll(".user-profile-head-info-r-c ul").forEach((ele) => {
            const allReadNum = ele.querySelector("li:nth-child(1) .user-profile-statistics-views .user-profile-statistics-num").innerText;
            const articleNum = ele.querySelector("li:nth-child(2) .user-profile-statistics-num").innerText;
            const rank = ele.querySelector("li:nth-child(3) .user-profile-statistics-num").innerText;
            const fans = ele.querySelector("li:nth-child(4) .user-profile-statistics-num").innerText;
            data = {
                allReadNum,articleNum,rank,fans
            }
        });
        
        // 个人成就
        document.querySelectorAll(".aside-common-box-achievement").forEach((ele) => {
            const like = ele.querySelector("li:nth-child(1) div").innerText;
            const comment = ele.querySelector("li:nth-child(2) div").innerText;
            const favorite = ele.querySelector("li:nth-child(3) div").innerText;
            const share = ele.querySelector("li:nth-child(4) div").innerText;
            achievement = {
                like,comment,favorite,share
            }
        });
        return {
            name,data,achievement
        };
    });
    
    // 将数据写入文件中
    fs.writeFile('../chrome/mycsdn.json', JSON.stringify(myData), function (err, data) {
        if (err) {
            throw err
        }
        console.log('文件保存成功,当前时间:' + new Date());
    })

    // 关闭tab页
    await page.close();
    // 关闭实例
    await browser.close();
})

最终实现效果:

在这里插入图片描述

到此我们就实现了定时爬取CSDN个人主页数据的操作,接下来我们一起来完成Chrome插件开发!

Chrome插件开发

先来创建一个 Chrome 插件项目叫 mycsdn:

mkdir mycsdn  # 创建插件项目
cd mycsdn # 进入项目根目录
touch manifest.json # 在项目根目录中创建一个名为 manifest.json 的文件

接下来我们简单编写 manifest.json文件,参数配置如下:

{
    "manifest_version": 2,
    "name": "CSDN个人数据",
    "version": "1.0",
    "description": "CSDN个人数据展示",
    "permissions": [
        "activeTab"
      ],
    "browser_action": {
        "default_title": "CSDN个人数据",
        "default_popup": "popup/popup.html",
        "default_icon": {
            "128": "icon/icon128.png"
        }
    }
}

然后我们在根目录创建popup文件夹,添加一个名为 popup.html 的文件,我们来完成点击弹出的页面结构:

<!DOCTYPE html>
<html>
<head>
	<title>CSDN个人数据展示</title>
  	<meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1.0">
  	<link rel="stylesheet" href="popup.css">
  	<script src="popup.js"></script>
</head>
<body>
	<div class="container">
		<div class="box">
			<div class="card-data content">
				<h2>个人数据</h2>
				<p>总阅读数</p>
				<p>文章数</p>
				<p>排名</p>
				<p>粉丝数</p>
			</div>
		</div>

    <div class="box">
			<div class="card-data card-achievement content">
				<h2>个人成就</h2>
				<p>点赞数</p>
				<p>评论数</p>
				<p>收藏数</p>
				<p>分享数</p>
			</div>
		</div>
	</div>
</body>
</html>

来点CSS装饰一下:

body {
    min-width: 400px;
    min-height: 300px;
    font-family: Arial, Helvetica, sans-serif;
    background-color: #f2f2f2;
    margin: 0;
    padding: 0;
}

.container {
  max-width: 800px;
  margin: 0 auto;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
  padding: 10px 20px;
  background: radial-gradient(circle, rgba(238,174,202,1) 0%, rgba(148,187,233,1) 100%);
}

.box {
  position: relative;
  height: 220px;
  align-items: center;
  transition: 0.5s;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
 }

 .box .content {
  position: relative;
  padding: 0px 40px 10px 40px;
  backdrop-filter: blur(10px);
  z-index: 1;
  transform: 0.5s;
  background-color: rgba(255, 255, 255, 0.8);
  border-radius: 20px;
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
  overflow: hidden;
  margin-bottom: 0;
  font-size: 18px;
  color: #666;
  flex-grow: 1;
  text-align: right;
}

.content::before {
  content: "";
  background-image: url("../bk1.jpg");
  background-repeat: no-repeat;
  background-size: cover;
  opacity: 0.5;
  filter: blur(1px);
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
}

.box .content p {
  font-size: 14px;
  font-weight: bolder;
  color: black;
}
 
.box .content h2 {
  font-size: 20px;
  margin-bottom: 10px;
  font-weight: bolder;
  color: black;
}

在这里插入图片描述

效果还不错,大家也可以根据自己的审美自己来设计页面

接下来我们来写JS,这里因为已经将数据存储在本地JSON文件中,所以我们用 XMLHttpRequest 对象来读取这个JSON文件,详细信息可以看一下注释:

// 当DOM加载完成时执行以下代码
document.addEventListener("DOMContentLoaded", function () {
    // 创建一个新的XMLHttpRequest对象
    let xhr = new XMLHttpRequest();

    // 指定要读取的文件路径
    xhr.open('GET', '../mycsdn.json', true);

    // 当请求完成时执行的回调函数
    xhr.onload = function() {
      if (xhr.status === 200) {
        // 将JSON字符串转换为JavaScript对象
        let data = JSON.parse(xhr.responseText);

        // 处理读取到的数据
        const allReadNum = document.querySelector("p:nth-of-type(1)");
        allReadNum.innerHTML = `总阅读数:${data.data.allReadNum}`;
      
        const articleNum = document.querySelector("p:nth-of-type(2)");
        articleNum.innerHTML = `文章数:${data.data.articleNum}`;
      
        const rank = document.querySelector("p:nth-of-type(3)");
        rank.innerHTML = `排名:${data.data.rank}`;
      
        const fans = document.querySelector("p:nth-of-type(4)");
        fans.innerHTML = `粉丝数:${data.data.fans}`;
      
        const like = document.querySelector(
          ".card-achievement p:nth-of-type(1)"
        );
        like.innerHTML = `点赞数:${data.achievement.like}`;
      
        const comment = document.querySelector(
          ".card-achievement p:nth-of-type(2)"
        );
        comment.innerHTML = `评论数:${data.achievement.comment}`;
      
        const favorite = document.querySelector(
          ".card-achievement p:nth-of-type(3)"
        );
        favorite.innerHTML = `收藏数:${data.achievement.favorite}`;
      
        const share = document.querySelector(
          ".card-achievement p:nth-of-type(4)"
        );
        share.innerHTML = `分享数:${data.achievement.share}`;
      }
    };
    // 发送请求
    xhr.send();

  // 设置插件图标
  chrome.browserAction.setIcon({ path: "icon/icon128.png" });
  // 设置插件标题
  chrome.browserAction.setTitle({ title: "CSDN个人数据展示" });
});

我们首先创建了一个XMLHttpRequest对象,然后使用open方法指定要读取的文件路径。接着我们定义了一个onload回调函数,在请求完成时执行。在这个回调函数中,我们首先检查请求的状态是否为200(表示成功),然后使用JSON.parse方法将JSON字符串转换为JavaScript对象,最后我们就可以处理读取到的数据将其显示在页面上。

在这里插入图片描述

进程管理工具PM2

到此为止,我们这个插件项目还剩最后一个问题没有解决:我们编写的这个nodejs 爬虫文件不可能一直在控制台运行,那么我们该怎么让这个文件一直运行从而来定时爬取更新JSON文件呢?

我们这里来用一个管理 Node.js 进程的第三方工具 PM2

PM2是一个流行的Node.js进程管理器,它可以帮助我们简化应用程序的部署、监控和管理:

  • 进程管理:PM2可以启动、停止、重启和删除进程,可以使用PM2来管理单个应用程序或多个应用程序。
  • 自动重启:如果进程崩溃或异常退出,PM2会自动重启它。
  • 监控和日志记录:PM2可以监控应用程序的CPU和内存使用情况,并将日志记录到文件中。
  • 负载均衡:如果运行多个实例,PM2可以使用负载均衡来将流量分配到不同的实例上。
  • 部署:PM2可以在生产环境中部署应用程序,可以将应用程序作为系统服务运行,并在系统启动时自动启动。

以下是一些PM2的常用命令:

  • pm2 start <file>:启动一个应用程序。
  • pm2 stop <id|name>:停止一个应用程序。
  • pm2 restart <id|name>:重启一个应用程序。
  • pm2 delete <id|name>:删除一个应用程序。
  • pm2 list:列出所有正在运行的应用程序。
  • pm2 monit:监视所有正在运行的应用程序的CPU和内存使用情况。

我们来安装一下 pm2:

npm install -g pm2

然后用 pm2 启动项目:

pm2 start /path/to/your/nodejs/script.js

这个命令会启动Node.js程序,并且在后台运行,即使关闭了终端也不会停止运行

在这里插入图片描述

如果想停止程序可以使用以下命令:

pm2 stop /path/to/your/nodejs/script.js

插件开发总结

本项目是Node爬虫和Chrome插件开发的一个综合案例,这个插件的功能非常实用,可以帮助我们更好地了解自己的CSDN博客个人数据。

我们首先用puppeteer编写node爬虫脚本爬取到了CSDN个人主页数据,然后将数据写入了JSON文件,并用node-schedule模块完成了定时爬取的功能。

之后我们完成了Chrome插件的主体开发,最后我们使用PM2进程管理工具让这个爬虫文件一直运行。

插件完整代码可以自取:https://github.com/KongC-X/node-creeper/tree/main/chrome

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C# WPF上位机开发(Web API联调)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 很多时候&#xff0c;客户需要开发的不仅仅是一个上位机系统&#xff0c;它还有其他很多配套的系统或设备&#xff0c;比如物流小车、立库、数字孪…

【Maven】报错合集

问题1&#xff1a;com.github.everit-org.json-schema:org.everit.json.schema:pom:1.12.1 failed to transfer from http://localhost:8081/repository/maven-public/ during a previous attempt 发现原来是maven的settings.xml文件配置出现了问题。首先是之前maven进阶学习时…

【Java】一文讲解Java类加载机制

Java 类加载机制是 Java 运行时的核心组成部分&#xff0c;负责在程序运行过程中动态加载和连接类文件&#xff0c;并将其转换为可执行代码。理解类加载机制&#xff0c;能更容易理解你一行行敲下的Java代码是如何在JVM虚拟机上运行起来。并且理解类加载机制之后&#xff0c;我…

SpringBoot整合Canal

一 linux docker compose版本 1.第一步&#xff1a;基础环境 &#xff08;1&#xff09;第1步&#xff1a;安装jak、maven、git、nodejs、npm yum install maven mvn -v 安装maven时会帮安装jdkyum install git git --version 2.27.0yum in…

提升客户体验!十大热门客户服务软件解决方案推荐

现代企业深切认识到客户关系对于成功至关重要。如今&#xff0c;顾客越来越偏向于个性化和情境化服务的企业。根据Forrester的研究&#xff0c;将优先考虑建立更好客户关系以实现长期增长将是2023年业务成功的关键。 为了评估和改善客户关系&#xff0c;您需要一个系统化的方式…

DataFunSummit:2023年数据湖架构峰会-核心PPT资料下载

一、峰会简介 现今&#xff0c;很多企业每天都有PB级的数据注入到大数据平台&#xff0c;经过离线或实时的ETL建模后&#xff0c;提供给下游的分析、推荐及预测等场景使用。面对如此大规模的数据&#xff0c;无论是分析型场景、流批一体、增量数仓都得益于湖仓一体等数据湖技术…

数据分析硬核工具Origin各版本安装指南

下载链接 https://pan.baidu.com/s/12mENFtRFdNaLzVKmE6w_Uw?pwd0531 1.鼠标右击【Origin 2022(64bit)】压缩包&#xff08;win11及以上系统需先点击显示更多“选项”&#xff09;选择【解压到 Origin 2022(64bit)】。 2.双击打开解压后的【Origin 2022(64bit)】文件夹。 3.…

【Matlab】CNN卷积神经网络时序预测算法

资源下载&#xff1a; https://download.csdn.net/download/vvoennvv/88681558 一&#xff0c;概述 CNN&#xff08;Convolutional Neural Network&#xff0c;卷积神经网络&#xff09;是一种前馈神经网络&#xff0c;主要用于处理具有类似网格结构的数据&#xff0c;例如图像…

2023十大编程语言及未来展望

2023十大编程语言及未来展望 1. 2023年十大编程语言排行榜2. 十大编程语言未来展望PythonCCJavaC#JavaScriptPHPVisual BasicSQLAssembly language 1. 2023年十大编程语言排行榜 TIOBE排行榜是根据互联网上有经验的程序员、课程和第三方厂商的数量&#xff0c;并使用搜索引擎&a…

Python中的用户交互函数详解,提升用户体验!

更多Python学习内容&#xff1a;ipengtao.com 用户进行交互的Python应用程序&#xff0c;有许多常用的用户交互函数可以帮助创建更具吸引力和友好的用户界面。本文将介绍一些常用的Python用户交互函数&#xff0c;并提供详细的示例代码&#xff0c;以帮助大家更好地理解它们的用…

数字人私人定制

数字人是什么&#xff1f; 在回答这个问题之前&#xff0c;我们先回答另一个问题&#xff0c;人如何与人工智能交流&#xff1f;目前可以通过文字、语音、电脑屏幕、手机屏幕、平板、虚拟现实设备等和人工智能交流&#xff0c;为了得到更好的交流体验&#xff0c;人工智能必然…

CANopen DS402 Homing方法分析

本文主要分析CANopen DS402中各种Homing方法。 一 装置通用结构 讲解Homing方法前&#xff0c;需要了解一下装置的通用结构&#xff0c; 装置一般左右各有一个limit switch&#xff0c;即限位开关&#xff0c;用来控制移动范围&#xff0c;分别叫negative限位开关和positive…

Flowable-升级为7.0.0.M2-第二节

目录 替换变化的类和配置把javax.servlet 替换为 jakarta.servlet修改redis的配置配置logging.level.org.springframework.boot.autoconfigureerror避免影响视听 替换变化的类和配置 把javax.servlet 替换为 jakarta.servlet import javax.servlet.ServletContext; import ja…

运行时错误‘53’文件未找到:MathPage.WLL,安装MathType后Word不能复制粘贴问题的解决

两步解决&#xff1a; 1. 打开Word-->文件-->选项-->信任中心-->信任中心设置-->受信任位置&#xff0c;解决宏问题 添加如下受信任位置&#xff0c; 我的路径&#xff1a;C:\Program Files\Microsoft Office\root\Office16\STARTUP\ 2. 找到MathType下的MathT…

1panel使用指南(一)面板安装

一、1panel简介 1Panel是杭州飞致云信息科技有限公司推出的产品 [1]&#xff0c;帮助用户实现快速建站。 [2]是一款现代化、开源的Linux服务器运维管理面板&#xff0c;于2023年3月推出&#xff0c;深度集成WordPress和Halo&#xff0c;一键完成域名绑定、SSL证书配置等操作&a…

元旦特辑:Note5---插入排序

目录 前言&#x1faa9; 1. 排序的概念运用&#x1f7e3; 1.1 排序的概念&#x1f7ea; 1.2 排序的运用&#x1f49c; 2. 直接插入排序&#x1f7e2; 2.1 基本思想&#x1f7e9; 2.2 思路分析&#x1f49a; 2.3 代码实现✅ 2.3.1 sort.h 2.3.2 sort.c 2.3.3 test.c …

c语言-指针练习题

目录 前言一、题目一二、题目二总结 前言 为了巩固c语言中关于指针知识点的掌握&#xff0c;本篇文章记录关于指针的练习题。 一、题目一 有n个整数&#xff0c;使前面各数顺序往后移动m个位置&#xff0c;最后m个数变成最前面的m个数 写一函数实现以上功能&#xff0c;在主函…

k8s搭建(五、k8s可视化管理工具Dashboard配置)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

2000-2022年上市公司股票流动性指标数据/股票流动性Amihud(原始数据+计算代码+计算结果)

2000-2022年上市公司股票流动性指标数据/股票流动性Amihud&#xff08;原始数据计算代码计算结果&#xff09; 1、时间&#xff1a;2000-2022年 3、指标&#xff1a;证券代码_没有单位、交易日期_没有单位、日个股交易金额_元、考虑现金红利再投资的日个股回报率_没有单位、交…

杭电新生赛 大雪球 二分

&#x1f468;‍&#x1f3eb; 题目地址 ✨ AC code import java.io.*; import java.util.*;public class Main {static BufferedReader in new BufferedReader(new InputStreamReader(System.in));static BufferedWriter out new BufferedWriter(new OutputStreamWriter(Sy…