
小爱课程表导入课程表功能开发-正方教务系统
前言
时间应该是在一年前了,发现学校的方正教务还没在小爱课表上上线,之前可能是上线过的学长给下线了,得自己手搓一个吧。主要实现的是小爱课程表的教务系统的导入功能,小爱课程表app是小米手机中一款功能强大的校园用户课程表管理服务软件,它能够智能地为用户提供AI课程表和分享功能,让用户能够轻松管理自己的课程安排。现在就来记录一下这次实现的过程。
步骤
小爱课表开发文档
1.下载开发者插件,v0.3.8 下载地址
解压到本地的某个位置
安装 以edge浏览器为例,其他浏览器烦请随机应变一下
浏览器打开edge://extensions/,前缀根据对应的浏览器进行修改
开启开发人员模式,点击加载解压缩的扩展,选择刚刚解压到的文件夹
开始使用 浏览器打开你所要操作的教务系统,完成登录等操作,到需要导入的课表页面
网页内点击鼠标右键,选择检查,打开Edge开发者工具 或者使用键盘F12随后,你就可以发现多出来的AiSchedule标签,点击它
登录点击个人中心Tab,点击立即登录按钮,在弹窗登录小米账号即可完成登录项目列表接下来介绍项目列表Tab中对项目的操作方法
新建项目 插件侧边栏选中项目列表,点击右下角加号,在出现的弹窗中完善项目信息教务链接请带上https://,另外尽可能填写学校官方URL,不要填写个人网站,否则可能在后续的审核中不通过学校名称需要在输入完成后点选下拉菜单中的学校,如果没有自己所在学校,请至侧边栏反馈中进行反馈
教务系统如果不清楚,选择自研教务填写完成后点击右侧保存按钮即可 注:对于每个开发者来讲,每个学校可以建立多个项目,以针对不同的学生群体或者校区之类的问题, 最好将特征写进项目名称方便用户查看,例如:正方-本科-东校区
代码
以下以方正教务为例
Provider 是用来获取html的函数,将获取到的html传给 Parser 进行数据处理,截取出对应的课程信息,再封装为规定的json格式数据返回
function scheduleHtmlProvider(iframeContent = "", frameContent = "") {
var sch = document.querySelector('#kblist_table')
if (!sch) {
let TriPrompto = `
没有获取到课表哦
导入流程:
>> 输入账号密码
>> 然后点击右上角头像旁三条横线
>> 依次: 选课>学生课表查询
>> 点击<一键导入>
`
alert(TriPrompto)
}
return sch.outerHTML
}Parser函数里不能使用document和window对象,因为这部分是在服务端解析的,用到了cheerio的环境
function weekStr2IntList(week) {
// 将全角逗号替换为半角逗号
week.replace(/,/g, ',');
let weeks = [];
// 以逗号为界分割字符串,遍历分割的字符串
week.split(",").forEach(w => {
if (w.search('-') != -1) {
let range = w.split("-");
let start = parseInt(range[0]);
let end = parseInt(range[1]);
for (let i = start; i <= end; i++) {
if (!weeks.includes(i)) {
weeks.push(i);
}
}
} else if (w.length != 0) {
let v = parseInt(w);
if (!weeks.includes(v)) {
weeks.push(v);
}
}
});
return weeks;
}
function getSections(str) {
let start = parseInt(str.split('-')[0])
let end = parseInt(str.split('-')[1])
let sections = []
for (let i = start; i <= end; i++) {
sections.push({ section: i })
}
return sections
}
function getTime(str) {
let t = str.split('节)')
let weekStr = t[1].replace(/周/g, '')
let weeks = getWeeks(weekStr)
return [weeks, getSections(t[0].replace('(', ''))]
}
function getWeeks(str) {
let flag = 0
if (str.search('单') != -1) {
flag = 1
str = str.replace('单', '')
} else if (str.search('双') != -1) {
flag = 2
str = str.replace('双', '')
}
let weeks = weekStr2IntList(str)
weeks = weeks.filter((v) => {
if (flag === 1) {
return v % 2 === 1
} else if (flag === 2) {
return v % 2 === 0
}
return v
})
return weeks
}
// 解析列表模式
function parseList(html) {
let _tri
let result = []
const $ = cheerio.load(html, { decodeEntities: false });
$('#kblist_table tbody').each(function (weekday) {
if (weekday > 0) {
$(this).find('tr').each(function (index) {
if (index > 0) {
let course = {}
$(this).find('td').each(function (i) {//_tri 修复部分课程无节数信息的问题
if (i == 0 && !/[u4e00-u9fa5]/.test($(this).text())) {
course.sections = getSections($(this).text())
_tri = course.sections
} else {
course.sections = _tri
course.name = $(this).find('.title').text()
let info = []
$(this).find('p font').each(function () {
let text = $(this).text().trim()
if (text.search('上课地点') != -1) {
text = text.replace('上课地点:', '')
}
info.push(text.split(':')[1].replace('XXX大学', ''))
})
let weekStr = info[0].replace(/周/g, '')
course.weeks = getWeeks(weekStr)
course.teacher = info[2]
course.position = info[1]
course.day = weekday
}
})
result.push(course)
}
})
}
})
return result
}
function scheduleHtmlParser(html) {
let result = []
result = parseList(html)
for (let tri = 0; tri < result.length; tri++) {
result[tri].position = result[tri].position.replace(/)|)/, '').replace(/(|(|楼/g, '-')
}
let _sectionTimes = [
{
"section": 1,
"startTime": "08:25",
"endTime": "09:10"
}, {
"section": 2,
"startTime": "09:20",
"endTime": "10:05"
}, {
"section": 3,
"startTime": "10:20",
"endTime": "11:05"
}, {
"section": 4,
"startTime": "11:15",
"endTime": "12:00"
}, {
"section": 5,
"startTime": "14:00",
"endTime": "14:45"
}, {
"section": 6,
"startTime": "14:55",
"endTime": "15:40"
}, {
"section": 7,
"startTime": "15:50",
"endTime": "16:35"
}, {
"section": 8,
"startTime": "16:45",
"endTime": "17:30"
}, {
"section": 9,
"startTime": "18:30",
"endTime": "19:15"
}, {
"section": 10,
"startTime": "19:25",
"endTime": "20:10"
}]
return { courseInfos: result, sectionTimes: _sectionTimes }
}Timer本代码的运行环境和Provider是一致的, 时间配置函数
完成上述三个主要的代码,提交给课表审核就可以了。


