用JavaScript写一个自动刷新网页通知软考成绩是否出来的脚本

4,186 阅读3分钟

本项目github:github.com/SHENLing062…

  • 简要说明 + 代码均在github中可下载
  • 请遵循MIT协议

1. 前言

由于今年考了软考,本就有点焦虑于自己在及格线上下徘徊,然后等待一个月后,很多考试公众号上开始号召入一些群以第一时间知道是否出成绩了等等。。。。

结果,不仅仅没有从那些群里获得有效信息,反而平添了很多焦虑感,自己也不可能在搬砖的时候跟着一起不停扣F5疯狂刷新页面。

就这么搞了一周多,心情不好睡不好后,怒而拾起老本行,用JS写了一个自动运行检测成绩网站是否出成绩了的自动运行脚本,让chrome自动通知我出成绩了。

写好的第一时间,我就退群了!!!!!身心轻松!!!😄

想要知道怎么使用的,可以直接看第2节。

想要知道这个脚本原理解析的,看后面,就可以自己修修补补用在其他地方了

2. autoRefresh.js使用说明

2.1 设置chrome,允许chrome发送通知

打开chrome的设置,添加允许通知该软考查询成绩 image.png

image.png

image.png

image.png

2.2 系统设置允许chrome通知显示在桌面上

image.png

image.png

2.3 进入目标刷新网站

软考成绩网站:query.ruankao.org.cn/score

按F12,打开控制台: image.png

复制下方代码进入控制台,回车运行

/*
 * @Author: ShenLing
 * @Date: 2021-12-19 14:48:27
 * @LastEditors: ShenLing
 * @LastEditTime: 2021-12-19 15:34:50
 */
// 设置:刷新间隔、考试时间string
timeout=prompt('页面刷新间隔(秒):'); // 每隔5s自动更新
compareText=prompt('考试时间', '2021年下半年')

// 初始化变量
count=0; // 已刷新次数
current=location.href; // 当前页面链接

if(timeout > 0) setTimeout('reload()', 1000 * timeout);
else location.replace(current);

// 自动重载页面
function reload() {
    // 刷新页面,更新刷新次数
    setTimeout('reload()', 1000 * timeout);
    count++;
    console.log(`每${timeout}秒自动刷新,刷新次数:${count}`);
    
    // 创建frame,保证刷新的是frame内容,而不会在刷新整个页面后清除掉本页执行代码,停止刷新
    fr4me='<frameset cols=\'*\'>\n<frame id src=\''+current+'\'/>';
    fr4me+='</frameset>';
    frameDOM = window.frames[0] ? window.frames[0].document : null;

    // 调用方法,检查是否满足条件
    checkInfo(frameDOM ? frameDOM : document)

    // 刷新嵌套的frame
    with(document) {
        write(fr4me);
        void(close());
    }
}

// 检查是否满足条件:包含xx字段,满足时开启浏览器通知提示
// 可根据实际情况调整该部分判断内容
function checkInfo(doc) {
    if (doc && doc.getElementsByTagName('li')) {
        targetDom=doc.getElementsByTagName('li');
        console.log(`当前查询:${compareText}`);

        for(var i = 0; i < targetDom.length; i++) {
            targetText=targetDom[i].innerText

            if (targetText && targetText === compareText) {
                console.log(`查询成功:${targetText}`);
                notify();
                break;
            }
        }
    }
}

// 浏览器通知提示
function notify() {
    // 判断是否开启了浏览器通知,若开启成功,则可以在自动刷新满足条件后正确发送通知
    // 可以打开 chrome://settings/content/notifications 设置“允许发送通知”链接
    if(window.Notification && Notification.permission !== "denied") {
        Notification.requestPermission(function(status) {
            var n = new Notification(`${compareText}软考出成绩了`, { body: '页面已更新!!!快来看成绩' }); 
        });
    }
}

2.4 运行结果

2.4.1 根据提示,输入网页自动刷新相隔秒数

image.png

2.4.2 根据提示,确认需要自动检测的考试时间

image.png

建议第一次运行,先输入2021上半年,进行测试

2.4.3 测试结果

控制台提示image.png

chrome提示image.png

提示成功后,进入该网页,强制刷新一下页面,就可以停止自动程序

别忘了测试成功后,修改为本年的考试年份重新运行哦~

3. 代码原理说明

3.1 简要说明

用setTimeout,对网页进行定时刷新,并对符合目标内容的元素进行检测,符合结果就发出通知

注意要点: 如果直接用setTimeout,会导致刷新一次后,控制带的代码就消失了,无法进行下一轮刷新,所以必须将页面document内容放置到<frame/>中,刷寻frame中的内容,就可以成功定时刷新内容了

3.2 代码分解说明

3.2.1 主程序

// 设置:刷新间隔、考试时间string
timeout=prompt('页面刷新间隔(秒):'); // 每隔5s自动更新
compareText=prompt('考试时间', '2021年下半年')

// 初始化变量
count=0; // 已刷新次数
current=location.href; // 当前页面链接

// 刷新页面
if(timeout > 0) setTimeout('reload()', 1000 * timeout);
else location.replace(current);

3.2.2 自动重载页面方法:reload()

通过js代码,创建frameset和frame,将原页面document放入frame中,强制刷新frame,并调用checkInfo(),判断内容是否满足条件

注意:frame中的document的获取方法,不能直接用document.getElementById()这种方法拿到,frame中是一整个document,所以需要用window.frames[0].document来拿到frame中的document。

// 自动重载页面
function reload() {
    // 刷新页面,更新刷新次数
    setTimeout('reload()', 1000 * timeout);
    count++;
    console.log(`每${timeout}秒自动刷新,刷新次数:${count}`);
    
    // 创建frame,保证刷新的是frame内容,而不会在刷新整个页面后清除掉本页执行代码,停止刷新
    fr4me='<frameset cols=\'*\'>\n<frame id src=\''+current+'\'/>';
    fr4me+='</frameset>';
    frameDOM = window.frames[0] ? window.frames[0].document : null;

    // 调用方法,检查是否满足条件
    checkInfo(frameDOM ? frameDOM : document)

    // 刷新嵌套的frame
    with(document) {
        write(fr4me);
        void(close());
    }
}

3.2.3 检查是否满足运行条件checkInfo()

下图是我们软考页面的元素,其中,通过找到这个“考试时间”的下拉列表元素可以知道,我们只要找到<li>标签中的文本内容是否是我们想要的年份,就可以判断这个时间的成绩是否可以查找到了。 image.png

所以核心就是这一段代码:

// index为li的序号
// doc为document,来自父方法传参,主要是为了通过<frame/>获取其中的document
doc.getElementsByTagName('li')[index].innerText

对于其他类似需求的页面,这一段判断条件可自定义设置

// 检查是否满足条件:包含xx字段,满足时开启浏览器通知提示
// 可根据实际情况调整该部分判断内容
function checkInfo(doc) {
    if (doc && doc.getElementsByTagName('li')) {
        targetDom=doc.getElementsByTagName('li');
        console.log(`当前查询:${compareText}`);

        for(var i = 0; i < targetDom.length; i++) {
            targetText=targetDom[i].innerText

            if (targetText && targetText === compareText) {
                console.log(`查询成功:${targetText}`);
                notify();
                break;
            }
        }
    }
}

3.2.4 浏览器通知的方法notify()

这里是为了让我们不用一直盯着网页看,所以开启了浏览器的app通知。但是在使用之前就需要开启各种权限。

// 浏览器通知提示
function notify() {
    // 判断是否开启了浏览器通知,若开启成功,则可以在自动刷新满足条件后正确发送通知
    // 可以打开 chrome://settings/content/notifications 设置“允许发送通知”链接
    if(window.Notification && Notification.permission !== "denied") {
        Notification.requestPermission(function(status) {
            var n = new Notification(`${compareText}软考出成绩了`, { body: '页面已更新!!!快来看成绩' }); 
        });
    }
}

4. 另一个思路:通过自动刷新接口来获取最新信息

我把这个思路补充在了另一篇文中: # 【衍生篇】用原生JavaScript来自动刷新get接口以获取更新数据