1.前言:
前文请参照我的以前的博客:
- 青果教务系统适配小爱课程表
本文代码现已开源:
- 小爱课程表适配gitee
- 小爱课程表适配github
去年的时候试着适配了我们学校的小爱课程表,但是由于水平不够,直接把接口以及参数照搬,代码如下面所示,没有动态修改接口基本意味着接口只能用一学期,这不符合程序员优雅的代码特点。
function scheduleHtmlProvider(iframeContent = "", frameContent = "", dom = document) {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://jwgl.hist.edu.cn/wsxk/xkjg.ckdgxsxdkchj_data10319.jsp?params=eG49MjAyMiZ4cT0wJnhoPTIwMjEwMDAwNTExMg==', false);
xhr.send();
return xhr.responseText;
}
2.解析接口:
我们的已知条件:
- 课程表的接口地址。
- 课程表的解析代码。(可参考上篇博客->青果教务系统适配小爱课程表)
-
我们的目的是了解传递什么参数,并且我们手动传递。
-
一般如果参数进行了加密,我们是很难解析的(开始我以为进行了加密)
xhr.open('GET', 'http://jwgl.hist.edu.cn/wsxk/xkjg.ckdgxsxdkchj_data10319.jsp?params=eG49MjAyMiZ4cT0wJnhoPTIwMjEwMDAwNTExMg==', false);
- 我们从这个接口中知道传递了一个params参数。
其实我开始并不知道这个参数是啥,但是最近写了一个二维码的程序,后面两个“==”太像base64了,然后。。。。,我就试着用base64反向解析一下。
然后就发现这其实是三个参数的转码,也没有任何其他的加密。
- 这三个参数简单就可以字面猜测
xn = 2022 //2022-2023学年
xq = 1 //0: 1学期, 1: 2学期
xh = 2021000005123 // 这个学号和我的学号不一样,我猜测是uid
- 手动获取参数:
学年学期很好获取,上半年就是第二学期,下半年就是第一学期。学年也是类似算法。
function getParam(){
const date = new Date();
let year = date.getFullYear();//获取完整的年份(4位)
const month = date.getMonth() + 1; //获取当前月份(0-11,0代表1月)
let xq = 0;
if(month < 7){
xq = 1;
year = year - 1;
}
return btoa('xn='+year+'&xq='+xq);
}
学号我获取折腾了半天,因为不是自己真实的学号,而是数据库的uid,所以我在js数据中一直找,发现唯一一次回传是在课程表页面,那个页面是嵌入式的,也许的小米的api的问题,使用js很难定位到。
- 也许不用学号就能获取。
最后我放弃传输学号参数,仅仅传递学年,学期参数,发现也可以获取课程表。我猜测服务器端可能认为这个是可有可无的参数(会话中已保存),没有做验证或者其他处理吧。
- 将学年和学期打包参数发送请求
return await request('get', 'gbk','http://jwgl.hist.edu.cn/wsxk/xkjg.ckdgxsxdkchj_data10319.jsp?params='+getParam());
这里我使用
btoa()
函数进行base64转码
3. 结果:
我最终通过手动传递,xh,xq的参数,完善了课程表的信息获取接口。
本文旨在记录获取接口参数一样的过程。
完整信息获取代码如下:
- 小爱课程表适配gitee
- 小爱课程表适配github
async function scheduleHtmlProvider(iframeContent = "", frameContent = "", dom = document) {
return await request('get', 'gbk','http://jwgl.hist.edu.cn/wsxk/xkjg.ckdgxsxdkchj_data10319.jsp?params='+getParam());
}
async function request(tag, encod, url) {
let formatText = (text, encoding) => {
return new Promise((resolve, reject) => {
const fr = new FileReader()
fr.onload = (event) => {
resolve(fr.result)
}
fr.onerror = (err) => {
reject(err)
}
fr.readAsText(text, encoding)
})
}
return await fetch(url, { method: tag })
.then((rp) => rp.blob().then((v) => formatText(v, encod)))
.then((v) => v)
.catch((er) => er)
}
function getParam(){
const date = new Date();
let year = date.getFullYear();//获取完整的年份(4位)
const month = date.getMonth() + 1; //获取当前月份(0-11,0代表1月)
let xq = 0;
if(month < 7){
xq = 1;
year = year - 1;
}
return btoa('xn='+year+'&xq='+xq);
}