非专业人士请切换到“如何使用”的章节,直接教你使用
前言
因为一周一次的青年大学习是需要进行统计并上传的,每次学习的人数未知、姓名顺序又可能打乱,如果人肉进行排查将会十分耗时耗力,特别是这种重复性工作做多了两个星期就很烦躁,因此开发了这个油猴脚本,只需要安装好,打开对应的页面就会弹出学习情况并可一键复制进行上报。
研发步骤
使用开发者工具分析
我们在青年大学习页面按下F12或者右键点击检查弹出开发者工具,点击开发者工具的选项卡中的网络,切换到网络请求的列表视图。
此时网络视图已经是清空状态,我们可以刷新页面,网络视频便会把与后端交互的请求一个个都原形毕露。
寻找已学名单的列表
首先需要确定我们要找什么,就是要找已学名单的列表,所以我们主要是找关键词 list,我们点击列表中的list请求,查看返回数据。
找到了请求就事半功倍了,我们对这个请求点击右键,复制fetch请求。
分析具体请求的参数和头部
我们来康康这个fetch请求具体是什么内容。
fetch("https://youthstudy.12355.net/apibackend/admin/young/organize/userList?organizedId=组织id&pageNo=页码", {
"headers": {
"accept": "application/json, text/plain, */*",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"cache-control": "no-cache",
"pragma": "no-cache",
"sec-ch-ua": "\"Chromium\";v=\"92\", \" Not A;Brand\";v=\"99\", \"Microsoft Edge\";v=\"92\"",
"sec-ch-ua-mobile": "?0",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"x-litemall-admin-token": "登录凭证(token)",
"x-litemall-identification": "young"
},
"referrer": "https://youthstudy.12355.net/backend/",
"referrerPolicy": "strict-origin-when-cross-origin",
"body": null,
"method": "GET",
"mode": "cors",
"credentials": "include"
});
我把我的敏感信息去除替换成中文,对应你复制到的内容则是已经自动填好的,显然,在以上fetch请求中,所需参数是组织id和页码,在请求头需要放入token便可以获取到已学名单。
小试牛刀,在控制台执行fetch请求
偷偷告诉你,刚刚生成的fetch请求直接粘贴到控制台运行是没有任何数据的哦!原因是该fetch请求没有写打印输出的语句。怎么写呢?这里我将教最简单的方法,当然如果你是大佬使用同步的方式实现那是更好了。
办法就是在fetch后面加个then,并打印返回回来的数据即可。
更多知识点:
fetch请求是什么?怎么用
fetch 同步异步
fetch("https://youthstudy.12355.net/apibackend/admin/young/organize/userList?organizedId=组织id&pageNo=页码", {
"headers": {
"accept": "application/json, text/plain, */*",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"cache-control": "no-cache",
"pragma": "no-cache",
"sec-ch-ua": "\"Chromium\";v=\"92\", \" Not A;Brand\";v=\"99\", \"Microsoft Edge\";v=\"92\"",
"sec-ch-ua-mobile": "?0",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"x-litemall-admin-token": "登录凭证(token)",
"x-litemall-identification": "young"
},
"referrer": "https://youthstudy.12355.net/backend/",
"referrerPolicy": "strict-origin-when-cross-origin",
"body": null,
"method": "GET",
"mode": "cors",
"credentials": "include"
}).then((e)=>{e.json().then(function(data){
//此时这里data就是返回回来的数据,打印里面的list属性
console.log(data.data.list);
})});
js基础数据比对
既然我们拿到了一手数据,那么就要进行数据比对了,康康有谁还没有学习青年大学习,既然需要比对就得准备一个数组用于存放所有的班级同学姓名。
然后使用js进行数据比对,这里我使用了对象存储学生的姓名,通过属性的方式访问可以确定该学生是否学习了青年大学习。
具体原理如下:
//定义一个对象,存放n个已学学生姓名
let obj ={ 'xiaoxi': 1, 'xiaohua': 1 }
//输出1
console.log(obj['xiaoxi'])
//输出undefined
console.log(obj['lihua'])
这样我们就可以通过这种方式obj[姓名]快速确定该学生是否有进行过青年大学习了。
首先对获取到数据进行处理,因为他不仅仅只有姓名,太多数据了,要转成如上一样的对象存储。
我把上面的fetch请求封装成get函数,传入组织id,页码,token即可发起请求,使用了同步的方式获取数据。
//获取学习名单
let data = await get(id,1,token)
//判断页码
let pages = Math.ceil(data.data.total / data.data.pageSize)
//把每页的数据存入对象
for(let i=1;i<pages +1 ;i++){
let data = await get(id,i,token)
for(let item of data.data.list){
learnName[item.name] = 1
}
}
console.log("获取到已学名单:")
console.log(learnName)
allName就是全部班级学生名字的数组,然后逐个循环遍历,比对数据。
for(let item of allName){
if(!learnName[item]){
noLearnName.push(item)
}
}
console.log("未学名单:")
console.log(noLearnName)
至此就可以得到了noLearnName未学名单的列表了。
更加通用的改进
显然,我们发现请求是需要组织id和token的,那么组织id每个团支书都是不一样的,我们怎么获取呢?token又得怎么获取呢?相信各位看完上面的分析一定能够找出答案。我把整个可以使用的油猴代码放到文章尾部,感兴趣的同学可以研究。
如何使用
一个可以使用油猴脚本的浏览器
什么360浏览器、edge浏览器、谷歌浏览器都是可以的。但是你得安装油猴插件先,点击你的浏览器的插件市场搜索tampermonkey点击安装,如果你的右上角出现一只猴子就是代表安装成功。温馨提示谷歌浏览器的插件市场需要fq才能访问。
添加脚本
点击添加新脚本就会打开一个脚本编辑页面。
粘贴脚本
把自动生成的内容删掉,然后粘贴文章底部的油猴脚本,按下ctrl + s保存脚本,或者点击文件-保存。保存后即可关闭页面。
尽情使用
此时你就可以尽情使用脚本给你带来的便携。
完整代码
// ==UserScript==
// @name 智能统计未学学生
// @namespace http://tampermonkey.net/
// @version 0.1
// @description 统计青年大学习的相关信息。
// @author xiaoxi
// @match https://youthstudy.12355.net/*
// @icon https://www.google.com/s2/favicons?domain=12355.net
// @grant none
// ==/UserScript==
//blog:blog.diyxi.top
(async function() {
'use strict';
/*
*配置全班团员姓名,需要按照下列的方式一个个输入,标点符号不能错!
*/
let allName = [
"黄大侠", "刘德华" , "雷军"
]
/*
*以下代码非专业人士勿改!!
*以下代码非专业人士勿改!!
*以下代码非专业人士勿改!!
*代码出现问题或者不可用请在博客留言!!blog.diyxi.top
*/
let learnName = {}
let noLearnName =[]
//获取cookie中的token
let token = getCookie("X-Litemall-Admin-Token")
//获取组织id
let id = await getId(token)
id = JSON.parse(id.data.entity).organizeId
//获取学习名单
let data = await get(id,1,token)
//判断页码
let pages = Math.ceil(data.data.total / data.data.pageSize)
//把每页的数据存入对象
for(let i=1;i<pages +1 ;i++){
let data = await get(id,i,token)
for(let item of data.data.list){
learnName[item.name] = 1
}
}
console.log("获取到已学名单:")
console.log(learnName)
console.log("班级名单:")
console.log(allName)
for(let item of allName){
if(!learnName[item]){
noLearnName.push(item)
}
}
console.log("未学名单:")
console.log(noLearnName)
let text = `班级团员人数${allName.length}人,已学人数${Object.values(learnName).length}人,未学名单:`
for(let item of noLearnName){
text = text + item + ","
}
let code =`
<div style="background-color: antiquewhite;z-index:99999;position: fixed;top: 0;right: 0;display: flex;flex-direction: column;">
<div id="xx_iframe" style="display: block;width: 400px;">
<h1 style="text-align: center;">小熙高级统计工具</h1>
<p>温馨提示:油猴脚本是权限非常高的,请勿安装来源不明的油猴脚本,当然除了diyxi.top网站里的哈哈哈。</p>
<p>已学名单:${JSON.stringify(learnName)}</p>
<p>未学名单:${JSON.stringify(noLearnName)}</p>
<h2>参考参学率:${ ( Object.values(learnName).length / allName.length).toFixed(2) * 100}%</h2>
<textarea style="width: 100%;" name="" id="" cols="30" rows="10">${text}</textarea>
</div>
<button onclick="document.getElementById('xx_iframe').style.display=='block'?document.getElementById('xx_iframe').style.display='none':document.getElementById('xx_iframe').style.display='block'">隐藏/打开</button>
</div>`
let div = document.createElement("div");div.innerHTML = code
document.body.appendChild(div)
async function get(id,page = 1,token) {
let res = await fetch(`https://youthstudy.12355.net/apibackend/admin/young/organize/userList?organizedId=${id}&pageNo=` + page, {
"headers": {
"accept": "application/json, text/plain, */*",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"cache-control": "no-cache",
"pragma": "no-cache",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"x-litemall-admin-token": token,
"x-litemall-identification": "young"
},
"referrer": "https://youthstudy.12355.net/backend/",
"referrerPolicy": "strict-origin-when-cross-origin",
"body": null,
"method": "GET",
"mode": "cors",
"credentials": "include"
});
let data = await res.json()
return data
}
async function getId(token) {
let res = await fetch("https://youthstudy.12355.net/apibackend/admin/young/QRCode", {
"headers": {
"accept": "application/json, text/plain, */*",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"cache-control": "no-cache",
"pragma": "no-cache",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"x-litemall-admin-token": token,
"x-litemall-identification": "young"
},
"referrer": "https://youthstudy.12355.net/backend/",
"referrerPolicy": "strict-origin-when-cross-origin",
"body": null,
"method": "POST",
"mode": "cors",
"credentials": "include"
});
let data = await res.json()
return data
}
// 获取指定名称的cookie
function getCookie(name){
var strcookie = document.cookie;//获取cookie字符串
var arrcookie = strcookie.split("; ");//分割
//遍历匹配
for ( var i = 0; i < arrcookie.length; i++) {
var arr = arrcookie[i].split("=");
if (arr[0] == name){
return arr[1];
}
}
return "";
}
})();