记一次从教务系统导出课程到小爱课程表

今天发现一个实用的小工具-小爱课程表适配工具,可以在我的教务系统中匹配数据,导入到小爱课程表中,还可以帮助同学导入,一次适配全校适用,只需要浏览器环境就行了,很方便

可以先看一下它的官方文档

https://ldtu0m3md0.feishu.cn/docs/doccnhZPl8KnswEthRXUz8ivnhb




好了我们来分析一下他是怎么导入的

基本的流程是通过解析页面的html获取课程数据,整理成标准的数据结构,然后在手机端保存课程

接下来我们举个例子

你看这就是我的教务系统的页面,里边很直观的可以看到我的课程

接下来我们就要获取这个页面的html

右侧的provider函数,就是用来获取html的函数,默认会传入document对象,

document就是整个页面的对象,它包含了页面的所有信息,包括页面的html

其实我们直接就能用document.html取到页面的html,但是呢,有些教务系统他喜欢内嵌iframe或者frame,所以我们的provider函数中就去递归了一下,去取到页面html,和页面中嵌套的iframe中的惠html,他可能嵌套了很多层,但是我们递归一下就全部取出来了

工具中给出了默认的provider函数,几乎能搞定所有的教务系统,点击右键运行,即可弹出html的页面,你可以在弹出的页面中随便查一下自己的课程,如果页面中包含了你的课程信息,那恭喜你他是完美适用的无需更改。如果弹出的html中不包含你的课程信息,那你就需要看看该怎么取更合适了。可以自己改写这个函数,调试一下。




我们拿到了页面的html,接下来我们解析这个html片段,从中提取课程信息,整理成符合要求的数据结构。

刚刚得到的html是一大长串字符串。我们可以用正则来匹配出对应的课程信息。当然这个正则就很复杂了(如果你是正则高手,当我没说...)。所以工具内提供了cheerio这个库,来帮助解析html

工具中内置了cheerio(页面在工具中已经被cheerio加载过了,直接是用$这个函数即可)

使用起来很简单的,参考https://juejin.im/post/5ea131f76fb9a03c8122d6b9

cheerio这个js模块就是解析xml结构的数据,然后直接可以通过id或者class来获取对应的xml片段

举个例子

通过观察我们发现 这个  id=kbgrid_table_0的div盒子,包含了所有的课程信息。那我们就取它,

$('#kbgrid_table_0')

 这样,你可以在console中运行这个函数,即可看到它的结果

或者这样,你可以取到所有的课程信息

$('#kbgrid_table_0').text()


但是这些课程都纠缠到一起了,不好分隔开

我们继续观察

可以发现这里的课程全都在tr  td 中


且每一个td中的课程都包含一个课程的所有信息,

每一个td中的span标签都包含了这个课程的每一个属性,比如课程名称、上课地点、老师等

所以我们先取这个   id=kbgrid_table_0的div下的所有td,然后循环它,取每个td下的所有span,然后判断 每个span的属性,比如这里的class=title即课程名称的span,title=‘上课地点’即上课地点的span,这样我们就会把所有的课程信息取出来。

这里有一个难点,上课周数、节数还是掺杂在一起的,它不像老师、上课地点这样直接取就行了,所以我们要对它特殊处理一下

大多数教务系统是这样的


这样的

你可以用简单的正则来取出开始周,结束周,也可以用js中的split来分割,我正则一般,所以选择split这种方式,然后来一个for循环把符合要求的周次放进一个数组,这里请注意单双周要特殊处理一下

举例子:

1-3,5-7(周)[01-02节]

我观察到“(周)”这个字符可以分割开周数和节数,所以我

let result=[]                                //先声明一个数组保存结果

let str='1-3,5-7(周)[01-02节]'

let weeks=str.split('(周)')[0]        //这样就取到了周,结果为1-3,5-7

let subWeek=weeks.split(',')     //这样就得到了[1-3,5-7],接下来我们循环它

for(let i=0;i

let week=subWeek[i]               //这里取到了 1-3,我们继续给他分割

let begin=week.split('-')[0]        //我们取到了开始周1

let end=week.split('-')[1]          //我们取到了结束周3

for(let j=begin;j

result.push(j)                          // 将符合要求的结果push进result数组

}

}


这样我们就取得了这节课的所有周,保存在了result中(当然你也可以直接用正则匹配开始周和结束周然后循环)

节数的处理也类似

这样我们就取到了所有课程的所有属性(通过两层for循环和多个if判断)

然后我们再把数据结构整理成官方文档中要的格式,就完工啦

记得关注我哈

你可能感兴趣的:(记一次从教务系统导出课程到小爱课程表)