用Python登陆新版正方教务系统获取课程表(及RSA加密密码实现)
前言
最近做一个微信小程序,需要登录教务系统。提前用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加密密码实现)相关推荐
- python爬虫学校正方教务系统获取全部成绩
python爬虫正方教务系统许昌学院 来自许昌学院的大四小菜鸡,疫情封在宿舍,闲来无事在宿舍爬了一下之前没成功的教务系统爬虫,当时觉得挺难的,今天发现这个还是挺简单的,这个程序参考了很多前辈大佬们的程 ...
- Python实现新版正方教务系统爬虫(二)
前言 哎对不起 我可能是silly boy 我想在学校里把去年的坑填了 但是发现新版的教务系统代码没传到git上 我现在就成了个对着空ide发呆的憨憨(代码在家里啦 所以填坑就再过会吧 那就稍微闲聊一 ...
- 新版正方教务系统导出课程表-油猴脚本
https://www.cnblogs.com/31415926535x/p/12244461.html 简介 这个油猴脚本主要是针对新版的正方教务系统,实现将课程表转化为一个 courses.ics ...
- 模拟登陆新版正方教务管理系统【可以获取学生基本/课表信息】
写在前面 博主登陆现在还可以正常使用,但是后面登陆成功,获取信息啥的有问题 登陆还是按照学长的来,模拟登陆新版正方教务管理系统 开始 学校教务系统改版,我直接copy博主代码获取学籍那里一直是获取到的 ...
- JSoup模拟登录新版正方教务系统(内网-教务系统)获取信息过程详解
新版正方教务系统登录界面: 目录 一.需求分析 二.模拟登录内网 三.模拟登录教务系统 四.爬取成绩和课表信息 参考文章 一.需求分析 需要访问教务系统,爬取出课表成绩等信息,并在自己所写的APP ...
- Java--使用httpClient模拟登陆正方教务系统获取课表
最近形如课程格子与超表课程表应用如雨后春笋般涌现,他们自动获取课程表是怎么实现的呢.于是我用Java实现了一下模拟登陆正方教务系统获取课表的过程. 首先,我们先了解一下网站登录的原理:当我们输入学号, ...
- go语言爬取新版正方教务系统数据
go语言爬取新版正方教务系统数据 学完go语言的基础之后已经过了一个多月了,开始想试着利用些时间写写博客,就打算将半个月前练着写的一个go爬虫小项目翻出来写写.由于之前对go爬虫的一些基础知识不熟悉, ...
- 用java计算学生绩点并排序_JS代码计算GPA平均学分绩点(适合新版正方教务系统)...
JS代码计算GPA平均学分绩点(适合新版正方教务系统)javascript 新版教务在某些功能上进步很大,可是在GPA统计上,只有全部科目的GPA,没有必修科目的GPA,因此只能本身去写了.java ...
- python实现高校教务管理系统_Python实现新版正方教务系统爬虫
目录~ 引入 需要什么软件? 模拟登陆 代码实现(登陆) 模拟获取成绩 代码实现(获取成绩) 解析成绩 测试(完成图) 作者的话 引入 就在我刚刚写完旧版正方系统爬虫的时候(旧版正方系统爬虫代码) 学 ...
最新文章
- Linux进程查看与管理
- bitmap数据格式
- spring mvc logback
- 工程师的基本功是什么?如何练习?听美团技术大咖怎么说
- python 颜色空间转换_python opencv入门 颜色空间转换(9)
- 大牛讲解Kubernetes实战
- php date( ymd_PHP DATE()
- SSM框架原理流程及使用方法
- 黑盒测试和白盒测试的区别
- spring boot mybatis 事务回滚
- 爬取分析雪球网实盘用户数据
- Musical Christmas Lights——一个圣诞树灯光✨随音乐节奏改变的前端开源项目
- 可换皮肤的Qt登录界面
- 【NS3】NS3安装 visualizer模块安装 (Windows+VMware+Kali) 2022.2
- What is Scala
- android—如何添加一个系统服务
- MCU微控制器在电动滑板车技术核心剖析
- HTML 中 id、name、class 区别
- 阿里P6和P7待遇差别有多大
- uni-app搜索功能前后端开发(页面)
热门文章
- 《Android App开发进阶与项目实战》出版后记
- c语言采用文件存储数据,C语言读写文件大全 之 基础篇
- 【操作系统原理】信号量及PV操作详解
- 【物理实验及其数据处理】 集成电路传感器特性测量及其应用
- lol查询服务器角色信息,游戏账号角色查询
- 基于matlab的禁止无功补偿,基于MATLAB的TSC-TCR型静止无功补偿器仿真研究.zip
- ADS设计不等分功分器
- ffmpeg mplayer x264 代码重点详解 详细分析
- Scrapy设置headers、cookies三种方法
- 域控服务器降级失败,windows2003域控制器升级和降级的图文教程