欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

程序员文章站 2022-05-02 10:02:49
...

    python作为一门编程语言,可以干好多好多事,可以说只要你想得到,没有它做不到的。自学python有一段时间了,现在此记录近段时间的所学成果——爬取学校教务网。

先贴最终效果图:

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

    首先是教务网网址

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

如果你的教务网也是这样的,那你算看对文章了。如果不是那你也可以学习爬取信息的思路。

1.信息获取第一步,模拟登录。

在此需要使用浏览器抓包工具,查看请求登录需要发送哪些信息。

教务网界面按F12,会弹出如下界面(作者使用的是win10自带的浏览器)

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

选择网络(360浏览器是network),开始抓包(也可以用wireshark)。准备好之后输入账号密码进行登录,很快network里就会出现很多条请求信息,我们进行的是登录操作,一般使用的方法都是“post”,而名称会包含login,很快找到下图的一条信息。

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

选择抓到的这条信息,查看正文,如下。

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

可以见到这里登录需要4个参数(其实是3条,有两条重复),我们可以确定yhm就是我们的用户名(学号)就是刚才输入的,mm肯定是密码,但怎么不是刚才输入的,加密了?不明白,那就查看源代码吧。

同样F12查看源代码

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

从中可以发现

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

现在知道密码为什么要重复了,看了半天也不知道密码是怎么加密的,最后在引用的JavaScript里看到原来是RSA的加密方式。

此时也许你会问什么是RSA,我也不知道,百度一番,看了大量的文章,RSA其实就是把密码进行因式分解那样,是一种主流的加密方式,安全性高,原来他还有公钥、私钥这一回事。那公钥、私钥怎么来呢?同样进行抓包,打开网页之前就抓。

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

exponent、modulus就是我们要找的公钥、私钥了。

然后在网页源码里找到csrftoken,如下

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

此外,登录一个网站还需要发送一般的参数,也就是请求标头

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

好了,理清楚的教务网的登录机制,开始动手码代码吧。

首先是获取公钥、私钥

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

发送此请求还需要时间参数,可以查看源代码获得,获取方式

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

其次是对输入的账号密码进行加密,此时导入一个RSA加密的包,需要注意编码格式。

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

此时就可以进行完整的登录操作了。

可以通过请求的返回结果来判断登录是否成功

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

好了,如果你做到了这一步,你就可以对教务网进行肆无忌惮得操作了。

查课表:

请求url:

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

解析查询返回的json:

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

查成绩:

请求URL:

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

解析json:

Python模拟登陆新版教务网获取课表、成绩(RSA加密)

此外还可以写一段自动评教、选课的代码,只要你能想到,都可以实现。

另外,如果你有兴趣可以把python代码修改成别的编程语言,例如java、C,你还可以改写成Android的,开发编写手机端的掌上教务网APP,甚至可以模仿超级课程表。

最后贴上源代码:

 def __init__(self,year,term):
        self.year = year
        self.term = term
        self.url1 = 'http://i.nbut.edu.cn:8066/jwglxt/kbcx/xskbcx_cxXskbcxIndex.html?gnmkdm=N253508&layout=default&su='+cumt_login.user        
        self.url2 = 'http://i.nbut.edu.cn:8066/jwglxt/kbcx/xskbcx_cxXskbcxIndex.html?doType=query&gnmkdm=N253508'
        self.url3 ='http://i.nbut.edu.cn:8066/jwglxt/kbcx/xskbcx_cxRsd.html?gnmkdm=N253508'
        self.url4 ='http://i.nbut.edu.cn:8066/jwglxt/kbcx/xskbcx_cxXsKb.html?gnmkdm=N253508'
                   
    def welcome(self):
        try:
            stu_name = self.req_2['xsxx']['XM']
            sch_stu = self.req_2['xsxx']['XH']
            institute = self.req_2['xsxx']['XNMC']
            classss = self.req_2['xsxx']['XKKG']
            # print(self.req_2)
            print('')
            print(stu_name+'同学,欢迎您!!!')
            print('')
            print('姓名:{}\t学号:{}\t\t学年:{}\t学期:{}'.format(stu_name,sch_stu,institute,classss))
            print('')
            for i in self.req_2['kbList']:
                print("课程名称:"+i['kcmc'])
                print("教师:"+i['xm'])
                print("上课地点:"+i['xqmc']+i['cdmc'])
                print("时间:"+i['jcs']+'\t'+i['zcd'])
                print('')
        except:
            print('无当前学期,请重试')
    def post_gradedata(self):
        try:
            data = {'_search':'false',
                    'nd':int(time.time()),
                    'queryModel.currentPage':'1',
                    'queryModel.showCount':'15',
                    'queryModel.sortName':'',	
                    'queryModel.sortOrder':'asc',
                    'time':'3',
                    'xnm':self.year,
                    'xqm':self.term
                    }
            data3 = {'xnm': self.year,
                    'xqh_id': self.term,
                    'xqm': self.term   
                }
            data4 = {'xnm': self.year,
                    'xqm': self.term   
            }       
            req_1 = super().sessions.post(self.url1,data = data,headers = cumt_login.header)
            req_2 = super().sessions.post(self.url2,data = data , headers = cumt_login.header)
            req_3 = super().sessions.post(self.url3,data = data3,headers = cumt_login.header)
            req_4 = super().sessions.post(self.url4,data = data4, headers = cumt_login.header)
            self.req_2 = req_4.json()
        except:
            print('获取失败,请重试...')
            time.sleep(2)
            exit()
 def __init__(self,year,term):
        self.year = year
        self.term = term
        self.url1 = 'http://i.nbut.edu.cn:8066/jwglxt/cjcx/cjcx_cxDgXscj.html?gnmkdm=N305005&layout=default&su='+cumt_login.user        
        self.url2 = 'http://i.nbut.edu.cn:8066/jwglxt/cjcx/cjcx_cxDgXscj.html?doType=query&gnmkdm=N305005'
    
    def welcome(self):
        try:
            stu_name = self.req_2['items'][0]['xm']
            sch_stu = self.req_2['items'][0]['xslb']
            institute = self.req_2['items'][0]['jgmc']
            classss = self.req_2['items'][0]['bj']
            print('')
            print('')
            print(stu_name+'同学,欢迎您!!!')
            print('')
            print('姓名:{}\t学历:{}\t\t学院:{}\t班级:{}'.format(stu_name,sch_stu,institute,classss))
            print('')
        except:
            print('无当前学期,请重试')
    def post_gradedata(self):
        try:
            data = {'_search':'false',
                    'nd':int(time.time()),
                    'queryModel.currentPage':'1',
                    'queryModel.showCount':'15',
                    'queryModel.sortName':'',   
                    'queryModel.sortOrder':'asc',
                    'time':'0',
                    'xnm':self.year,
                    'xqm':self.term
                    }
            req_1 = super().sessions.post(self.url1,data = data,headers = cumt_login.header)
            req_2 = super().sessions.post(self.url2,data = data , headers = cumt_login.header)
            self.req_2 = req_2.json()
            # print(self.req_2)
        except:
            print('获取失败,请重试...')
            time.sleep(2)
            exit()
    
    def print_geades(self):
        try:
            plt = '{0:{4}<15}\t{1:{4}<6}\t{2:{4}<6}\t{3:{4}<4}' 
            gk = 0
            zkm = 0
            print('')
            print('--------------------------------------------------------------------------------')
            print(plt.format('课程','成绩','绩点','教师',chr(12288)))
            print('--------------------------------------------------------------------------------')
            for i in self.req_2['items']:
                print(plt.format(i['kcmc'],i['bfzcj'],i['jd'],i['jsxm'],chr(12288)))
                if i['bfzcj'] < 60:
                    gk +=1
                zkm += 1
            print('--------------------------------------------------------------------------------')
            print('')
            print('通过科目数:{}{}'.format(zkm-gk,'门'))
            print('挂科科目数:'+str(gk)+'门')
            print('')
            print('')
        except:
            print('无当前学期,请重试')

 

 

如果你觉得麻烦,也可以在此处下载,作者把需要导入的包也一并上传。

 

 

你可以再这里下载代码。

如果你没有下载积分,可以再下发留下邮箱,作者看到会第一时间发送给你。

作者码字不易,如果你觉得好的话,记得点赞。

最后还要感谢Eddie_Ivan大佬,没有他的文章的帮助,作者突破不了关键的难点。