微信定时推送LeetCode每日一题,再也不怕没人喊你刷题了

前段时间发过一篇关于微信机器人开发的文章,讲述了如何快速开发一个微信机器人,本篇文章就来实现一个最近开发的一个功能案例,在这个案例中会遇到了各种问题,可以帮助大家减少自己去踩坑的时间。通过此案例也可以帮助你去扩想一些更符合你的使用场景。

如果你还不了解微信机器人的开发,建议先阅读下面的文章:

只需要6行代码,就可以开发一个微信机器人

通过微信定时推送功能,每日向用户发送LeetCode的每日题目。这项服务不仅方便了编程爱好者和求职者随时练习算法题,而且解决了缺乏动力或组织者来提醒刷题的问题,鼓励读者养成每日刷题的学习习惯。

功能描述

  • 每日通过微信消息的方式,把leetcode当日题目推送到指定联系人或群聊中。
  • 给机器人发送消息,随机推送一条leetcode的题目

推送的消息中需要包含题目的一些基本信息。比如:题目名称、难度等级、通过率、解题地址等。

为了可以更直观的了解详情,也需要将题目内容进行推送。由于内容一般都是比较大的,所以采用图片的方式推送是一个不错的选择。效果如下:

在这里插入图片描述

如果你对今天的题目比较感兴趣,就可以通过点击解题地址去打卡今日任务,即使电脑不在身边,也可通过题目内容图片了解到今日题目内容

实现

在这里插入图片描述

  • 接收消息:接收到指定的消息后,推送内容,例如:每日一题、随机出题
  • 定时推送:每日定时将题目题送到指定联系人或群聊
  • 获取数据:获取leetcode题目内容
  • 整合数据:生成需要推送的文本和图片消息
  • 发送消息:将内容推送给用户

1. 获取数据

打开leetcode官网首页,可以看到在题目列表中第一项就是当题的题目。
在这里插入图片描述

打开控制台,可以看到有很多相同的URL请求,使用的是graphQL查询。一个一个的点看查看返回内容,找到今日题目的请求。
在这里插入图片描述
在这里插入图片描述

复制请求参数,构建请求。

// 获取今日题目
async function fetchTodayLeetCode() {const url = "https://leetcode.cn/graphql/";return new Promise((resolve) => {axios.post(url, {query: "\n    query questionOfToday {\n  todayRecord {\n    date\n    userStatus\n    question {\n      questionId\n      frontendQuestionId: questionFrontendId\n      difficulty\n      title\n      titleCn: translatedTitle\n      titleSlug\n      paidOnly: isPaidOnly\n      freqBar\n      isFavor\n      acRate\n      status\n      solutionNum\n      hasVideoSolution\n      topicTags {\n        name\n        nameTranslated: translatedName\n        id\n      }\n      extra {\n        topCompanyTags {\n          imgUrl\n          slug\n          numSubscribed\n        }\n      }\n    }\n    lastSubmission {\n      id\n    }\n  }\n}\n    ",variables: {},operationName: "questionOfToday",}).then((res) => {try {const data = res.data.data.todayRecord[0];resolve(data);} catch (error) {resolve("");}}).catch(() => {resolve("");});});
}

拿到返回的数据后,就可以提取想要发送的数据信息。

// 获取今天LeetCode题目
async function getTodayLeetCode() {//  获取题目数据const data = await fetchTodayLeetCode();if (!data) return "";const question = data.question;const { title, titleCn, titleSlug, difficulty, acRate } = question;let difficultyCn = "未知";switch (difficulty) {case "Hard":difficultyCn = "困难";break;case "MEDIUM":difficultyCn = "中等";break;case "EASY":ifficultyCn = "简单";break;default:break;}const url = `https://leetcode.cn/problems/${titleSlug}/description`;const text = `----每日一题----\n题目:${titleCn}\n难度:${difficultyCn}\n通过率:${Number(acRate * 100).toFixed(2)}%\n解题地址:${url}`;return text;
}

在首页的请求只会返回题目的基本信息,没有内容信息,此时需要点击进入题目详情页面,按照同样的方法,找到查询题目详情的接口来获取详情内容。
在这里插入图片描述
在这里插入图片描述

这里需要注意修改查询参数titleSlug的值,改为题目中返回的titleSlug字段。

// 查询题目详情
async function fetchLeetCodeQuestionDetail(titleSlug) {const url = "https://leetcode.cn/graphql/";return new Promise((resolve) => {axios.post(url, {query: "\n    query questionTranslations($titleSlug: String!) {\n  question(titleSlug: $titleSlug) {\n    translatedTitle\n    translatedContent\n  }\n}\n    ",variables: {titleSlug: titleSlug,},operationName: "questionTranslations",}).then((res) => {try {const data = res.data.data.question;resolve(data);} catch (error) {resolve("");}}).catch(() => {resolve("");});});
}

2. 内容截图

题目详情接口中返回的详情内容格式为html字符串的格式,很容易就联想到将其渲染后再进行截图。

如果是在前段环境下,这很容易做到,可以直接创建一个元素,设置innerHtml为题目内容,变成真正的dom元素。然后使用html2canvas转成图片即可。

但是在node环境下是没有window对象的,相关的API也不可用。这里介绍一个强大的node.js库puppeteer来实现这个过程。

Puppeteer 是一个 Node.js 库,提供了一套高级 API 通过 DevTools 协议控制 Chrome 或 Chromium 浏览器,用于自动化测试、网页抓取、生成页面截图和 PDF 等,它的功能还远不止这些。

async function htmlText2Image(content, savePath) {// 启动一个新的浏览器实例const browser = await puppeteer.launch();// 创建一个新的页面const page = await browser.newPage();// 设置要渲染的HTML内容;const htmlContent = `<!DOCTYPE html><html><head><meta charset="UTF-8"><title>leetcode题目</title><style>pre {white-space: pre-wrap;}
</style></head><body>${content}</body></html>`;// 将HTML内容设置为页面的内容await page.setContent(htmlContent);// 将页面渲染为图片并保存到文件await page.screenshot({path: savePath,fullPage: true,});// 关闭浏览器await browser.close();
}

对图片中的内容可以灵活的自定义,比如添加额外信息,添加一些样式等,就跟我们开发一个页面一样简单。

// ...
const detail = await fetchLeetCodeQuestionDetail(titleSlug);
// 截图
const { translatedTitle, translatedContent } = detail;
await htmlText2Image(`<h1>${translatedTitle}&nbsp;&nbsp;<span style="font-size:18px;font-weight:400">难度:${difficultyCn}&nbsp;&nbsp;通过率:${Number(acRate * 100).toFixed(2)}%</span></h1>${translatedContent}<div style="text-align:center;"><img src="https://resource.dengzhanyong.com/images/9ce7efc7-d880-470d-8864-9c29e242c4f5.png" style="height:120px;"/></div>`,"这里是图片存储的路径"
);// ...

封装推送的图片消息

const { FileBox } = require("file-box");const imagePath = '这里是图片的路径';
const imageFileBox = FileBox.fromFile(imagePath);

踩坑记录

到现在为止,上面一切在本地运行测试都没问题,但当我部署到服务器(centos)上时,一系列的问题就出现了。

1. 服务器上没有chrome浏览器
使用sudo yum install chromium 去安装,会报找不到chromium这个包,可能是源不对,并且这种方式安装的chromium会有很多问题,不推荐。

推荐直接下载安装包,然后手动安装:

wget https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm
mkdir ./google_chrome
mv google-chrome-stable_current_x86_64.rpm ./google_chrome/  
cd  ./google_chrome    # 进入目录
yum -y install google-chrome-stable_current_x86_64.rpm

2. glibc版本过低
centos7默认的glibc函数库的版本为2.17,chromium要求glibc-2.25版本,因此需要升级glibc版本。可能不同版本的chromium要求glibc不同,根据实际错误提示进行升级。

#查询已安装的glibc版本
strings /lib64/libc.so.6 | grep GLIBC

在这里插入图片描述

3. chromium拥有很多依赖库,必须把所有的必须依赖库全部安装上才可以

sudo yum install libatk1.0-0 libatk-bridge2.0-0 libcups2 libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libpango1.0-0 libasound2 

4. 需要禁用沙箱模式

在这里插入图片描述

在启动浏览器是,需要配置--no-sandbox 参数,其的作用是禁用沙箱模式,这可以解决在一些环境中由于权限问题无法正常启动浏览器的问题,并提高浏览器的启动速度。

// 启动一个新的浏览器实例
const browser = await puppeteer.launch({args: ["--no-sandbox"],
});

5. 截图中无法显示中文
在这里插入图片描述

使用Puppeteer进行截图时,会出现部分中文显示方块字乱码的问题。这并不是Puppeteer的问题,实际上是Linux字体库对中文支持不好的原因。
只需要给服务器的Linux系统安装支持的中文字体库即可。

sudo yum install wqy-microhei-fonts.noarch -y
sudo yum install wqy-unibit-fonts.noarch -y
sudo yum install wqy-zenhei-fonts.noarch -y

消息推送

最后只需要创建定时器,或接收到指定消息后执行上面的流程即可。

1. 创建推送列表配置信息

const = LEETCODE_PUSH_LIST: [{name: "前端筱园交流群",id: "@@6ab29397570b5672d1b53945432b5ce1326dc43682bf3de4dff4c3579afa4325",date: "0 30 9 * * *",}
]

2. 封装定时器

const schedule = require("node-schedule");
function setSchedule(date, callback) {schedule.scheduleJob(date, callback);
}

3. 机器人登录后启动定时器

bot.on("login", onLogin);async function onLogin(user) {console.log(`${user} 登录成功`);setTimeout(() => {leetCodePush(this);}, 5000);
}/*** 每日一题推荐* @param {*} that*/
async function leetCodePush(that) {console.log("开启每日一题推荐");const list = config.LEETCODE_PUSH_LIST;if (list.length) {for (const item of list) {const { title, name, date, count } = item;setSchedule(date, async () => {const message = await getTodayLeetCode();// 找到目标群聊const room = await findRoom(that, name);if (room && message) {// 如果是多条消息,则逐条推送if (isArray(message)) {for (const item of message) {await room.say(item);}} else {room.say(message);}}});}}
}

收到指定消息回复中间的流程都一样,只是需要判断下收到的消息是否匹配,如果是个人发送就回复给个人,如果是群聊中被@,就推送到群聊中。
在这里插入图片描述
在这里插入图片描述

通过本案例不仅是希望你了解学习到更多的关于**微信机器人chromiumpuppeteer**等相关知识。更是为了让你开拓自己的想象空间,开发更多的适合自己的使用场景,给你的生活带来便利。

写在最后

最后,如果你觉得这个功能对你很有帮助,但是自己又不想去开发,回复“交流群”加入前端筱园交流群,就可以免费体验啦。
可以在群内添加前端筱园机器人为好友,独自享受更多功能服务。

欢迎访问我的个人网站:www.dengzhanyong.com

欢迎加入前端筱园交流群:
描述文字
关注我的公众号【前端筱园】,不错过每一篇推送

描述文字

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

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

相关文章

Profibus_DP转ModbusTCP网关模块连马保与上位机通讯

Profibus转ModbusTCP网关模块&#xff08;XD-ETHPB20&#xff09;广泛应用于工业自动化领域。例如&#xff0c;可以将Profibus网络中的传感器数据转换为ModbusTCP协议&#xff0c;实现数据的实时监控和远程控制。本文介绍了如何利用Profibus转ModbusTCP网关&#xff08;XD-ETHP…

【AMBA】AHB总线中的HTRANS、HSIZE、HBURST以及1K边界问题

HTRANS、HSIZE和HBURST共同决定下一次数据传输的地址。 HTRANS[1:0]定义传输类型 HTRANS[1:0]主机传输状态描述00IDLE空闲表示没有进行数据传输&#xff0c;默认状态。主设备虽然可能已经占用了总线&#xff0c;但是还没有开始传输数据。从设备需要返回OKAY响应01BUSY忙主设备…

前端面试39(关于git)

针对前端开发者的Git面试题可以覆盖Git的基础概念、常用命令、工作流程、团队协作、以及解决冲突等方面。以下是一些具体的Git面试 Git基础知识 什么是Git&#xff1f; Git是一个分布式版本控制系统&#xff0c;用于跟踪计算机文件的更改&#xff0c;并协调多个人共同在一个项…

基于视觉的具身导航

基于视觉的具身导航 背景 什么是&#xff08;视觉的&#xff1f;&#xff09;具身导航 输入机器人观测的当前图像 o t o_t ot​和目标图像 o G o_G oG​&#xff0c;输出当前时间步的控制动作 u t u_t ut​&#xff0c;最终到达指定地点的算法流程。 通用的评价指标 性能指…

Git常见命令和用法

Git 文件状态 Git 文件 2 种状态: 未跟踪:新文件&#xff0c;从未被 Git 管理过已跟踪:Git 已经知道和管理的文件 常用命令 命令作用注意git -v查看 git 版本git init初始化 git 仓库初始化之后有工作区、暂存区(本地库)、版本库git add 文件标识暂存某个文件文件标识以终…

人工智能建立在对象存储上的真正原因

tl;dr: 在这篇文章中&#xff0c;我们将探讨 AI 工作负载依赖高性能对象存储的四个技术原因。 1. 对非结构化数据没有限制 在当前的机器学习范式中&#xff0c;性能和能力与计算成比例&#xff0c;计算实际上是数据集大小和模型大小的代理&#xff08;神经语言模型的缩放定律&a…

C#开发:下载node.js指定版本

一、打开官网 二、找到指定版本 三、选择程序包msi下载 四、验证下载是否成功 cmd输入&#xff1a; node -v npm -v

请跳至打印机属性的“Adobe PDF设置”页面,取消选择“仅停靠系统字体;不使用文档字体”

场景&#xff1a; 当使用adobe pdf打印时&#xff0c;出现如下提示“请跳至打印机属性的“Adobe PDF设置”页面&#xff0c;取消选择“仅停靠系统字体&#xff1b;不使用文档字体””&#xff0c;该如何解决。 描述 □“仅停靠系统字体&#xff1b;不使用文档字体” 复选本框…

基坑安全:自动化监测系统的革新力量

在日新月异的基坑工程领域&#xff0c;基坑安全自动化监测系统犹如一位守护者&#xff0c;以其独特的优势&#xff0c;为工程的安全与质量保驾护航。该系统集先进的测量仪器、计算机技术与现代传感技术于一体&#xff0c;对基坑的围护结构及周边环境进行全方位、高精度的实时监…

从零开始学量化~Ptrade使用教程(四)——股票普通买卖与回购业务

股票普通买卖 股票买入 通过选择委托方向实现股票的买入与卖出&#xff0c;可根据输入的价格自动查询可买数量。 用鼠标点击【买入】&#xff0c;如图所示&#xff1a; 输入股票代码并选中后&#xff0c;选择委托类型&#xff0c;若为限价类型&#xff0c;输入委托价格&#xf…

【漏洞复现】锐捷校园网自助服务系统 任意文件读取

声明&#xff1a;本文档或演示材料仅用于教育和教学目的。如果任何个人或组织利用本文档中的信息进行非法活动&#xff0c;将与本文档的作者或发布者无关。 一、漏洞描述 锐捷校园网自助服务系统是用于学校网络管理的一个平台&#xff0c;login_judge.jsf接口存在任意文件读取…

中职网络安全B模块渗透测试server2380

使用nmap扫描添加参数-sV Flag:2.4.38 添加参数-A不然扫不全 &#xff08;这两题可以直接加-sV -A&#xff09; Flag: 4.3.11-Ubuntu 根据nmap扫描发现系统为ubuntu系统&#xff0c;ubuntu操作系统在某些版本中默认包含一个名为"ubuntu"的用户帐户。这是为了方…

重生奇迹mu自带四重箭加穿透的弓

1.烈风射手 烈风射手是自带四重箭加穿透的弓之一。该职业的技能树中有一个叫做“四箭连发”的技能&#xff0c;可以让玩家在一次攻击中发射四支箭矢&#xff0c;每支箭矢都带有穿透效果。 2.影魅猎人 影魅猎人也是自带四重箭加穿透的弓之一。该职业的技能树中有一个叫做“穿…

案例分享:Qt modbusTcp调试工具(读写Byte、Int、DInt、Real、DReal)(当前v1.0.0)

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://blog.csdn.net/qq21497936/article/details/140313789 红胖子(红模仿)的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片…

Backend - C# 操作PostgreSQL DB

目录 一、安装 Npgsql 插件 &#xff08;一&#xff09;作用 &#xff08;二&#xff09;操作 &#xff08;三&#xff09;注意 二、操作类 &#xff08;一&#xff09;操作类 1.NpgsqlConnection类 &#xff08;1&#xff09;作用 &#xff08;2&#xff09;引入 &a…

[高频SQL50题(基础版)]第五百八十四题,寻找用户推荐人

题目&#xff1a; 表: Customer ---------------------- | Column Name | Type | ---------------------- | id | int | | name | varchar | | referee_id | int | ---------------------- 在 SQL 中&#xff0c;id 是该表的主键列。 该表的每一…

儿童房灯具什么牌子好?几款儿童房灯具款式墙裂分享

随着科技的不断发展和生活方式的改变&#xff0c;儿童青少年近视率的增长趋势引起了人们的关注。近视不仅对孩子们的视力健康构成威胁&#xff0c;还可能对他们的学习和日常生活带来不便。因此&#xff0c;如何有效地预防和改善儿童青少年的视力问题成为了一个亟待解决的课题。…

2024学生党蓝牙耳机什么牌子好?品牌高性价比蓝牙耳机推荐

2024年&#xff0c;对于追求性价比和品质的学生党来说&#xff0c;选择一款合适的蓝牙耳机是提升学习和生活品质的重要一环。面对市场上琳琅满目的蓝牙耳机产品&#xff0c;2024学生党蓝牙耳机什么牌子好&#xff1f;如何找到既满足音质需求又具备高性价比的款式呢&#xff1f;…

高考后的IT专业启航:暑期预习指南与学习路线图

文章目录 每日一句正能量前言&#xff1a;启航IT世界&#xff0c;高考后的暑期学习之旅基础课程预习指南基础课程预习指南&#xff1a;构建你的IT知识大厦引言一、计算机科学导论二、编程语言入门三、操作系统基础四、数据结构与算法五、网络基础六、数据库原理结语 技术学习路…

02STM32软件安装新建工程

STM32软件安装&新建工程 1.软件安装&#xff1a;1.1Keil5 MDK安装1.2安装器件支持包离线安装支持包在线安装支持包 1.3软件注册&#xff1a;1.4安装驱动STLINK驱动JLink驱动在此文件夹下USB转串口 2.新建工程2.1STM32开发方式&#xff1a;1.寄存器2.标准库3.HAL库 固件库压…