前言

最近做一个微信小程序,需要登录教务系统。提前用python尝试一下登录接口,并获取到课表打印出来。

我们学校用到新版正方教务系统,长这个样子。


相比旧版的教务系统,唯一好处是不用输入二维码方便爬虫登录。但登录时用到RSA加密密码发送请求。


正文

分析网页:

在网页上填上随便写的账号密码,点击登录。开发者工具记录如下:

首先它点击登录后,提交一个表单,Form Data一共有4个数据

提交的数据 解释
csrftoken 为了防止跨站域请求伪造 。在登录页源码里有,每次刷新都会变更
yhm 输入的用户名
mm 输入的密码,被加密过。我们主要关注这一个加密过程

csrftoken 如图所示:

另外,在开发者工具里,我们还需要注意服务器的一条get请求

查看它返回的数据

这条Get请求作用:发送当前时间戳,返回公共密钥。并且每次modulus的数据不同,有人会问,这个东西干嘛的?
其实,这是在密码加密时用到的公钥,如果你也曾看过它的密码加密代码,就会了解到。
我们翻一下网站的Javascript,看看密码加密过程

 $.getJSON(_path+"/xtgl/login_getPublicKey.html?time="+new Date().getTime(),function(data){modulus = data["modulus"];exponent = data["exponent"];});
     if($("#mmsfjm").val() == '0'){$("#hidMm").val($("#mm").val());}else{var rsaKey = new RSAKey();rsaKey.setPublic(b64tohex(modulus), b64tohex(exponent));var enPassword = hex2b64(rsaKey.encrypt($("#mm").val()));$("#mm").val(enPassword);$("#hidMm").val(enPassword);   }

具体加密过程:首先获取modulus,exponent。将他们从base64转16进制,再通过RSA算法生成公钥。
用公钥将密码生成私钥从16进制转回base64。变成最终加密的密码。

至此,我们分析完成,在python里面要做的步骤:
1、获取到csrftoken
2、发送时间戳获取到PublicKey
3、生成RSA加密的密码
4、POST请求登录


python实现过程

登录中唯一难点是生成rsa加密的密码,有大神把js的rsa算法写成python,具体在github里。我已经下载并放在项目文件夹下,直接调用。

头部文件:

import requests
import time
from lxml import etree
from hex2b64 import HB64
import RSAJS

重中之重的RSA加密过程:

    def Get_RSA_Password(self):# 生成RSA加密密码rsaKey = RSAJS.RSAKey()rsaKey.setPublic(HB64().b642hex(self.modulus),HB64().b642hex(self.exponent))self.enPassword = HB64().hex2b64(rsaKey.encrypt(self.Password))

与JavaScript原加密算法对比:

登录代码:

    def Longin_Home(self):# 登录信息门户,成功返回session对象self.Get_indexHtml()self.Get_csrftoken()self.Get_PublicKey()self.Get_RSA_Password()login_data = [("csrftoken", self.csrftoken),("yhm", self.Username),("mm", self.enPassword),("mm", self.enPassword)]login_html = self.session.post(self.login_url + self.now_time,data=login_data)# 当提交的表单是正确的,url会跳转到主页,所以此处根据url有没有跳转来判断是否登录成功if login_html.url.find("login_slogin.html") == -1: # -1没找到,说明已经跳转到主页print("登录成功")return self.sessionelse:print("用户名或密码不正确,登录失败")exit()

获取课程表代码

class TimeTable():def __init__(self,session,table_url):data = {"xnm":2018,"xqm":12}table_info = session.post(table_url,data = data).json()for each in table_info["kbList"]:plt = r'{} | {:<8s} | {:<13s} | {:<15s} | {:<22s}'print(plt.format(each["xqjmc"], each["jc"], each["cdmc"], each["zcd"], each["kcmc"]))

登录成功后已经可以为所欲为了,获取课程表只是一个简单操作,就没怎么优化代码了。

完整代码:

# -*- coding=utf-8 -*-
import requests
import time
from lxml import etree
from hex2b64 import HB64
import RSAJSclass Longin():def __init__(self,user,password,login_url,login_KeyUrl):# 初始化程序数据self.Username = userself.Password = passwordnowTime = lambda:str(round(time.time()*1000))self.now_time = nowTime()self.login_url = login_urlself.login_Key = login_KeyUrldef Get_indexHtml(self):# 获取教务系统网站self.session = requests.Session()self.session.headers.update({"User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36","Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8","Accept-Encoding": "gzip, deflate","Accept-Language": "zh-CN,zh;q=0.9","Cache-Control": "max-age=0","Connection": "keep-alive","Referer": self.login_url+ self.now_time,"Upgrade-Insecure-Requests": "1"
})self.response = self.session.get(self.login_url+ self.now_time).content.decode("utf-8")def Get_csrftoken(self):# 获取到csrftokenlxml = etree.HTML(self.response)self.csrftoken = lxml.xpath("//input[@id='csrftoken']/@value")[0]def Get_PublicKey(self):# 获取到加密公钥key_html = self.session.get(self.login_Key + self.now_time)key_data = key_html.json()self.modulus = key_data["modulus"]self.exponent = key_data["exponent"]def Get_RSA_Password(self):# 生成RSA加密密码rsaKey = RSAJS.RSAKey()rsaKey.setPublic(HB64().b642hex(self.modulus),HB64().b642hex(self.exponent))self.enPassword = HB64().hex2b64(rsaKey.encrypt(self.Password))def Longin_Home(self):# 登录信息门户,成功返回session对象self.Get_indexHtml()self.Get_csrftoken()self.Get_PublicKey()self.Get_RSA_Password()login_data = [("csrftoken", self.csrftoken),("yhm", self.Username),("mm", self.enPassword),("mm", self.enPassword)]login_html = self.session.post(self.login_url + self.now_time,data=login_data)# 当提交的表单是正确的,url会跳转到主页,所以此处根据url有没有跳转来判断是否登录成功if login_html.url.find("login_slogin.html") == -1: # -1没找到,说明已经跳转到主页print("登录成功")return self.sessionelse:print("用户名或密码不正确,登录失败")exit()class TimeTable():def __init__(self,session,table_url):data = {"xnm":2018,"xqm":12}table_info = session.post(table_url,data = data).json()for each in table_info["kbList"]:plt = r'{} | {:<8s} | {:<13s} | {:<15s} | {:<22s}'print(plt.format(each["xqjmc"], each["jc"], each["cdmc"], each["zcd"], each["kcmc"]))if __name__ == "__main__":# 登录主页urllogin_url = "http://学校主页/jwglxt/xtgl/login_slogin.html?language=zh_CN&_t="# 请求PublicKey的URLlogin_KeyUrl = "http://学校主页/jwglxt/xtgl/login_getPublicKey.html?time="# 登录后的课表URLtable_url = "http://学校主页/jwglxt/kbcx/xskbcx_cxXsKb.html?gnmkdm=N2151"zspt = Longin("输入你的账号","输入你的密码",login_url,login_KeyUrl)response_cookies = zspt.Longin_Home()table = TimeTable(response_cookies,table_url)

最后需要注意的地方:
为了代码更有移植性,方便各位在自己的学校的教务系统登录,整个代码几乎封装好了。也即是说,只要你的学校也使用新版正方教务系统,那么稍微阅读代码(特别是if "__name__"==__main__:这部分),改三个网站地址便可调用。

程序里调用的hex2b64、RSAJS库和完整代码我已经打包好了,上传到csdn里。或者你也可以在评论留下邮箱,看到了就发给你。



CSDN下载链接:

https://download.csdn.net/download/koevas/11010479

百度云:

链接:https://pan.baidu.com/s/1gkMXCzXdx5NWUUs8bvGM-A
提取码:it2x


参考资料:

https://github.com/Pusnow/pyjsbn-rsa
https://blog.csdn.net/qq_33278884/article/details/80936714
https://www.v2ex.com/t/433971

用Python登陆新版正方教务系统获取课程表(及RSA加密密码实现)相关推荐

  1. python爬虫学校正方教务系统获取全部成绩

    python爬虫正方教务系统许昌学院 来自许昌学院的大四小菜鸡,疫情封在宿舍,闲来无事在宿舍爬了一下之前没成功的教务系统爬虫,当时觉得挺难的,今天发现这个还是挺简单的,这个程序参考了很多前辈大佬们的程 ...

  2. Python实现新版正方教务系统爬虫(二)

    前言 哎对不起 我可能是silly boy 我想在学校里把去年的坑填了 但是发现新版的教务系统代码没传到git上 我现在就成了个对着空ide发呆的憨憨(代码在家里啦 所以填坑就再过会吧 那就稍微闲聊一 ...

  3. 新版正方教务系统导出课程表-油猴脚本

    https://www.cnblogs.com/31415926535x/p/12244461.html 简介 这个油猴脚本主要是针对新版的正方教务系统,实现将课程表转化为一个 courses.ics ...

  4. 模拟登陆新版正方教务管理系统【可以获取学生基本/课表信息】

    写在前面 博主登陆现在还可以正常使用,但是后面登陆成功,获取信息啥的有问题 登陆还是按照学长的来,模拟登陆新版正方教务管理系统 开始 学校教务系统改版,我直接copy博主代码获取学籍那里一直是获取到的 ...

  5. JSoup模拟登录新版正方教务系统(内网-教务系统)获取信息过程详解

    新版正方教务系统登录界面: 目录 一.需求分析 二.模拟登录内网 三.模拟登录教务系统 四.爬取成绩和课表信息 参考文章 一.需求分析   需要访问教务系统,爬取出课表成绩等信息,并在自己所写的APP ...

  6. Java--使用httpClient模拟登陆正方教务系统获取课表

    最近形如课程格子与超表课程表应用如雨后春笋般涌现,他们自动获取课程表是怎么实现的呢.于是我用Java实现了一下模拟登陆正方教务系统获取课表的过程. 首先,我们先了解一下网站登录的原理:当我们输入学号, ...

  7. go语言爬取新版正方教务系统数据

    go语言爬取新版正方教务系统数据 学完go语言的基础之后已经过了一个多月了,开始想试着利用些时间写写博客,就打算将半个月前练着写的一个go爬虫小项目翻出来写写.由于之前对go爬虫的一些基础知识不熟悉, ...

  8. 用java计算学生绩点并排序_JS代码计算GPA平均学分绩点(适合新版正方教务系统)...

    JS代码计算GPA平均学分绩点(适合新版正方教务系统)javascript 新版教务在某些功能上进步很大,可是在GPA统计上,只有全部科目的GPA,没有必修科目的GPA,因此只能本身去写了.java ...

  9. python实现高校教务管理系统_Python实现新版正方教务系统爬虫

    目录~ 引入 需要什么软件? 模拟登陆 代码实现(登陆) 模拟获取成绩 代码实现(获取成绩) 解析成绩 测试(完成图) 作者的话 引入 就在我刚刚写完旧版正方系统爬虫的时候(旧版正方系统爬虫代码) 学 ...

最新文章

  1. Linux进程查看与管理
  2. bitmap数据格式
  3. spring mvc logback
  4. 工程师的基本功是什么?如何练习?听美团技术大咖怎么说
  5. python 颜色空间转换_python opencv入门 颜色空间转换(9)
  6. 大牛讲解Kubernetes实战
  7. php date( ymd_PHP DATE()
  8. SSM框架原理流程及使用方法
  9. 黑盒测试和白盒测试的区别
  10. spring boot  mybatis 事务回滚
  11. 爬取分析雪球网实盘用户数据
  12. Musical Christmas Lights——一个圣诞树灯光✨随音乐节奏改变的前端开源项目
  13. 可换皮肤的Qt登录界面
  14. 【NS3】NS3安装 visualizer模块安装 (Windows+VMware+Kali) 2022.2
  15. What is Scala
  16. android—如何添加一个系统服务
  17. MCU微控制器在电动滑板车技术核心剖析
  18. HTML 中 id、name、class 区别
  19. 阿里P6和P7待遇差别有多大
  20. uni-app搜索功能前后端开发(页面)

热门文章

  1. 《Android App开发进阶与项目实战》出版后记
  2. c语言采用文件存储数据,C语言读写文件大全 之 基础篇
  3. 【操作系统原理】信号量及PV操作详解
  4. 【物理实验及其数据处理】 集成电路传感器特性测量及其应用
  5. lol查询服务器角色信息,游戏账号角色查询
  6. 基于matlab的禁止无功补偿,基于MATLAB的TSC-TCR型静止无功补偿器仿真研究.zip
  7. ADS设计不等分功分器
  8. ffmpeg mplayer x264 代码重点详解 详细分析
  9. Scrapy设置headers、cookies三种方法
  10. 域控服务器降级失败,windows2003域控制器升级和降级的图文教程