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

本文详细介绍了如何使用Python模拟登陆新版正方教务系统,并实现成绩获取。通过Fiddler抓包分析,获取必要的数据如publickey、csrftoken,利用RSA加密算法处理密码,最终成功实现登陆和成绩查询。同时,文章展示了遇到的问题及解决方案,适合初学者参考学习。
摘要由CSDN通过智能技术生成

目录~

引入

需要什么软件?

模拟登陆

代码实现(登陆)

模拟获取成绩

代码实现(获取成绩)

解析成绩

测试(完成图)

作者的话

引入

就在我刚刚写完旧版正方系统爬虫的时候(旧版正方系统爬虫代码)

学校就出了新版的正方教务系统

dd5fc64518994ea0a9bf92c9266b75ba.jpg

估计是装空调的钱有的多

那就开始讲解叭~

1fc7e1c0b3374085b13dce6070419517.jpg

需要什么软件?

基本的

Python! (我最喜欢3.x的版本啦)

一个你喜欢的IDE! (顺手的IDE事半功倍哦)

requests(爬虫基本都大家都明白的吧~)

BeautifulSoup(解析结构化数据很好用啦)

re(正则化表达式html还算好用吧)

time(这是网址中神秘代码的来源哦)

datetime(这个可以不加啦 我做了和数据库的链接方便记录时间)

subprocess(委屈 是不经意间没有办法捡来的解决办法)

sys(防止报错意外停止啦)

扩展的

Fiddler 4!(模拟爬虫是真滴好用)

模拟登陆

首先我们启动Fiddler 然后正常访问一下教务系统

d4985e40d459471385f8ed74c4c5ad48.png

发现了这两条事件

第78条事件就是访问主页面啦

但是第80条事件返回了一个json格式的数据 不知道干嘛的 先保存下来吧

输入账号密码

a969394090c14c91863d6320b03cada4.png

在Fiddler中出现了一条post数据

46a3b7f4a20d4b85bc17510e93064ee0.png

点一下WebForms看看带了什么数据进去

51b8cce04c1b467a8fb0f2e2dccaa3e7.jpg

Body

Value

time

time库里的time~

csrftioken

不知道什么东西 怎么没出现过

yhm

用户名是明文唉 大家心知肚明就好了

mm

这个就是输入的密码了 一看就经过了加密

什么??加密过了??那是怎么加密的呢

在主页面经过审查元素发现了js的文件

ef439ff9f8b44b9f9a7b89967febd975.png

啊~在login.js里面 找到了这些代码

$.getJSON(_path+"/xtgl/login_getPublicKey.html?time="+new Date().getTime(),function(data){

modulus = data["modulus"];

exponent = data["exponent"];

});

------我是分割符------

var rsaKey = new RSAKey();

rsaKey.setPublic(b64tohex(modulus), b64tohex(exponent));

var enPassword = hex2b64(rsaKey.encrypt($("#mm").val()));

$("#mm").val(enPassword);

$("#hidMm").val(enPassword);

大概翻译一下就是

获取了publishkey之后使用publishkey对明文的密码做RSA算法加密再使用BASE64填充

723bf242257d483d9713c461160fb968.jpg

升级了系统不就是不用验证码了吗 为什么做爬虫更累了呢

381a7ea0c59e4381a006a4c07e5ebe8a.jpg

总结一下

保存PublishKey

对密码进行加密

获取csrftoken

登陆!

代码实现(登陆)

首先准备一个session(会话)

session = requests.Session()

time_now = int(time.time())

session.headers.update({

'Accept': 'text/html, */*; q=0.01',

'Accept-Encoding': 'gzip, deflate',

'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0',

'X-Requested-With': 'XMLHttpRequest',

'Connection': 'keep-alive',

'Content-Length': '0',

'Content-Type': 'application/x-www-form-urlencoded',

'Host': 'qjxyjw.hznu.edu.cn',

'Referer': 'http://qjxyjw.hznu.edu.cn/jwglxt/xtgl/index_initMenu.html?jsdm=&_t=' + str(time_now),

'Upgrade-Insecure-Requests': '1'

})

至于这个头是怎么来的 详情Fiddler

# 准备publickey

url = 'http://qjxyjw.hznu.edu.cn/jwglxt/xtgl/login_getPublicKey.html?time=' + str(time_now)

r = session.get(url)

publickey = r.json()

提一下这个csrftoken 找来找去最后在访问主页面的时候找到了

# 准备csrftoken

url = 'http://qjxyjw.hznu.edu.cn/jwglxt/xtgl/login_slogin.html?language=zh_CN&_t=' + str(time_now)

r = session.get(url)

r.encoding = r.apparent_encoding

soup = BeautifulSoup(r.text, 'html.parser')

csrftoken = soup.find('input', attrs={'id': 'csrftoken'}).attrs['value']

说一下这个加密 虽然github上面有大佬从js里面移植过来的rsa算法 但是我无论如何都用不来

只好用别人的java程序 在python里面使用txt对密码传输(虽然很low但是是无奈之举了)

eeab5e9bf19b4c318633f23013ac11bc.gif

url = r"C:\Users\Administrator\Desktop\new_jiaowu"

f = open(url + r"\code.txt", "w")

f.write(studentid + '\n')

f.write(studentpwd + '\n')

f.write(publickey['modulus'] + '\n')

f.write(publickey['exponent'] + '\n')

f.close()

try:

subprocess.Popen('code.exe', shell=False, close_fds=True)

except:

print("启动加密程序错误")

sys.exit()

time.sleep(1)

with open(url + r"\encode.txt", 'r') as f:

list1 = f.readlines()

for i in range(0, len(list1)):

list1[i] = list1[i].rstrip('\n')

id = list1[0]

rsacode = list1[1]

f.close()

if id != studentid:

print("RSA加密错误...等待调试")

sys.exit()

对应的java代码在笔记本里 给个空位=。=

等待更新

嘿嘿嘿东西都准备好了 尝试登陆吧

try:

url = 'http://qjxyjw.hznu.edu.cn/jwglxt/xtgl/login_slogin.html'

data = {

'csrftoken': csrftoken,

'mm': rsacode,

'mm': rsacode,

'yhm': studentid

}

result = session.post(url, data=data)

return result.text

except Exception as e:

print(e)

如果密码输入错误的话会有提示框 这里使用in就可以简单的实现判断了

if '用户名或密码不正确' in result.text:

return "用户名或密码不正确"

最后 封装一下 就实现了主页面登陆的按钮啦

贴个代码

def login(studentid, studentpwd, session):

time_now = int(time.time())

# 准备publickey

url = 'http://qjxyjw.hznu.edu.cn/jwglxt/xtgl/login_getPublicKey.html?time=' + str(time_now)

r = session.get(url)

publickey = r.json()

# 准备csrftoken

url = 'http://qjxyjw.hznu.edu.cn/jwglxt/xtgl/login_slogin.html?language=zh_CN&_t=' + str(time_now)

r = session.get(url)

r.encoding = r.apparent_encoding

soup = BeautifulSoup(r.text, 'html.parser')

csrftoken = soup.find('input', attrs={'id': 'csrftoken'}).attrs['value']

# 加密密码

url = r"C:\Users\Administrator\Desktop\new_jiaowu"

f = open(url + r"\code.txt", "w")

f.write(studentid + '\n')

f.write(studentpwd + '\n')

f.write(publickey['modulus'] + '\n')

f.write(publickey['exponent'] + '\n')

f.close()

try:

subprocess.Popen('code.exe', shell=False, close_fds=True)

except:

print("启动加密程序错误")

sys.exit()

time.sleep(1)

with open(url + r"\encode.txt", 'r') as f:

list1 = f.readlines()

for i in range(0, len(list1)):

list1[i] = list1[i].rstrip('\n')

id = list1[0]

rsacode = list1[1]

f.close()

if id != studentid:

print("RSA加密错误...等待调试")

sys.exit()

# 单击登录按钮

try:

url = 'http://qjxyjw.hznu.edu.cn/jwglxt/xtgl/login_slogin.html'

data = {

'csrftoken': csrftoken,

'mm': rsacode,

'mm': rsacode,

'yhm': studentid

}

result = session.post(url, data=data)

return result.text

except Exception as e:

print(e)

模拟获取成绩

老样子 我们先模拟登陆使用Fiddler看看是怎么一个过程

b732ffe661d649faa4d0058abd91f4a2.jpg

这里可以一次性查询所有成绩有一点点方便

29fac9443a2f403d9f86f5bff08c5330.jpg

铛铛 在Fiddler中发现了如下数据

5786239e4d9c45dd8de20127e23d30f4.png

Body

Value

xnm

学年名

xqm

学期名

_search

固定false

nd

这个和之前的time一样的啦 都是time库里面的time函数整数化一下就好了

query*

固定的 照抄照抄

time

固定0(总觉得这个的存在是正方有点问题)

还是提一下这里学期名 发现第一学期发送的是3 第二学期发送的是12

811aee5bb4b14579a1db3dc6abf3104b.jpg

代码实现(获取成绩)

def score_page(session, year, term):

url = 'http://qjxyjw.hznu.edu.cn/jwglxt/cjcx/cjcx_cxDgXscj.html?doType=query&gnmkdm=N305005'

# 定义所有学期 3为第一学期 12为第二学期

if term == "1":

term = "3"

elif term == "2":

term = "12"

try:

data = {'_search': 'false',

'nd': int(time.time()),

'queryModel.currentPage': '1',

'queryModel.showCount': '15',

'queryModel.sortName': '',

'queryModel.sortOrder': 'asc',

'time': '0',

'xnm': year,

'xqm': term

}

result = session.post(url, data=data)

result = result.json()

return result

except:

return '[Error]获取该学期成绩失败'

解析成绩

既然成绩我们都获取到啦 还很方便给的是json数据 so 你懂了吗

stu_name = result['items'][0]['xm']

sch_stu = result['items'][0]['xslb']

institute = result['items'][0]['jgmc']

stu_class = result['items'][0]['bj']

print('姓名:{}\t学历:{}\t\t学院:{}\t班级:{}'.format(stu_name, sch_stu, institute, stu_class))

# dt = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

plt = '{0:{4}<15}\t{1:{4}<6}\t{2:{4}<6}\t{3:{4}<4}'

for i in result['items']:

print(plt.format(i['kcmc'], i['bfzcj'], i['jd'], i['jsxm'], chr(12288)))

# sql.insert_score(studentid, year, term, i['kcmc'], i['bfzcj'], i['jd'], i['jsxm'], dt)

因为后面我做好了和sql数据库的写入 作为演示 我都注释掉啦

测试(完成图)

嗝。。因为加密密码的环境问题 之后用笔记本再贴进来啦 给个空位=。=

(我是图片)

作者的话

为了这个程序真的是心力憔悴(写博客的格式更累)

但是还是结束啦~

ec28fce9da98496b98998ae4ecd027a1.jpg

希望能帮助到学习爬虫的各位~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值