简 介:此系统针对全球某工商每学期都要学生填写的学生互评,于可视化界面进行一键填写操作。
关键词:python, tikinter,gui,requests,爬虫,桌面程序
前言
最近一直在学爬虫的scrapy框架,学得有些累了,想着可不可以做些比较有意思的事情。正好之前有个学长曾经写过学校的学生事务管理平台自动填写系统,所以打算将其优化一下,并通过Tkinter模块做出用户可视化界面。
一、实际效果
分为一键满分评分与具体评分两种办法,适用于不同群体的需求。
二、使用步骤
1.引入库与全局变量
代码如下(示例):
from tkinter import *
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
import tkinter.messagebox
page_index = 1
2.自动填写之post请求
代码如下(示例):
# 第一级:学校登录界面结构不变,可直接抓包下一级网址,不需要进行数据解析,故不做处理
requests.packages.urllib3.disable_warnings() # 以防网站需要验证证书
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36 Edg/103.0.1264.71'
}
session = requests.session()
# 第二级:赋值参数负载,进行登录,目前验证码不进行校对,故可省略,并需存储登录cookie
second_url = 'https://xssw.zjgsu.edu.cn/api/v1/login'
data = {
'password': ety_mm.get(),
'unionid': 'null',
'xgh': ety_zh.get(),
}
second_page_json = session.post(url=second_url, headers=headers, data=data).json()
session.cookies['token'] = second_page_json['data']['access_token']
# 第三级:对测评详情页面发起get请求,获得json响应,以供后面逐个提交请求
third_url = 'https://xssw.zjgsu.edu.cn/api/v1/home/complex/evaluate/getGroupList?set_id=180&type=1'
third_page_json = session.get(url=third_url, headers=headers).json()
fourth_url = 'https://xssw.zjgsu.edu.cn/api/v1/home/complex/evaluate/group'
student_amount = 0
student_index = 0
total_score = 0
for it in third_page_json['data']:
if CheckVar[student_index].get():
if page_index == 1:
Type = '品德素质'
else:
Type = '心理素质'
if stu_name[student_index].split('已完成测评')[0] == Type:
print(it['xm'] + stu_name[student_index])
else:
in_data = {"option1": int(ety_pj1.get()), "option2": int(ety_pj2.get()), "option3": int(ety_pj3.get()),
"option4": int(ety_pj4.get()), "option5": int(ety_pj5.get()), "set_id": "121",
"type": page_index,
"xgh": it['xgh']}
session.post(url=fourth_url, headers=headers, json=in_data).json()
total_score = int(ety_pj1.get()) + int(ety_pj2.get()) + int(ety_pj3.get()) + int(ety_pj4.get()) + int(
ety_pj5.get())
Lstbox.insert('end',
'学生{}:{} {} 评分为:{} 完成测评!'.format(student_amount + 1, it['xm'], Type, total_score))
stu_name[student_index] = Type + '已完成测评'
student_amount += 1
student_index += 1
Lstbox.insert('end','你对每位学生的评分为{} 共{}位学生测评成功!'.format(total_score, student_amount))
lb_error.configure(text='测评结束!')
tkinter这个模块自己也是突发奇想地想去学习的,所以算是一边学一边写,所以慢慢地写到后面发现自己写崩了,整个程序感觉就像是为了交互而交互,整体结构十分冗余。
这边是以“具体评分”的子函数为例的,“全部满分评分”与其基本相同。
3.Tkinter的可视化界面
if __name__ == '__main__':
root = Tk()
root.title('浙商大学生事务管理平台自动填写互评 by:小泽不偷懒')
root.geometry('880x580')
lb_zh = Label(root, text='学号:', font=('等线', 20), width=20, height=2)
lb_zh.place(height=50, width=85, relx=0.2, rely=0.2)
ety_zh = Entry()
ety_zh.place(height=25, width=265, relx=0.3, rely=0.22)
lb_mm = Label(root, text='密码:', font=('等线', 20), width=20, height=2)
lb_mm.place(height=50, width=85, relx=0.2, rely=0.3)
ety_mm = Entry(show='*')
ety_mm.place(height=25, width=265, relx=0.3, rely=0.32)
lb_error = Label(root, text='请输入学号与密码后进行操作!', font=('等线', 15), width=20, height=2, fg='red')
lb_error.place(height=20, width=280, relx=0.31, rely=0.38)
btn_pf1 = Button(root, text='具体评分', font='等线', relief=RAISED,
command=lambda: spider_1())
btn_pf1.place(height=28, width=120, relx=0.62, rely=0.22)
btn_pf2 = Button(root, text='全部满分评分', font='等线', relief=RAISED,
command=lambda: spider_2())
btn_pf2.place(height=28, width=120, relx=0.62, rely=0.32)
# 评分各小项
lb_pj = Label(root, text='品德素质评价', font=('等线', 12), width=20, height=2)
lb_pj.place(height=25, width=95, relx=0.79, rely=0.35)
btn = Button(root, text='切换', font=('等线', 10), relief=RAISED, command=lambda: change_page(page_index))
btn.place(height=23, width=39, relx=0.92, rely=0.35)
lb_pj1 = Label(root, text='政治素养:', font=('等线', 10), width=20, height=2)
lb_pj1.place(height=25, width=85, relx=0.78, rely=0.4)
ety_pj1 = Entry()
ety_pj1.place(height=15, width=35, relx=0.89, rely=0.409)
ety_pj1.insert(0, '20')
lb_pj2 = Label(root, text='法制观念:', font=('等线', 10), width=20, height=2)
lb_pj2.place(height=25, width=85, relx=0.78, rely=0.44)
ety_pj2 = Entry()
ety_pj2.place(height=15, width=35, relx=0.89, rely=0.449)
ety_pj2.insert(0, '20')
lb_pj3 = Label(root, text='诚实守信:', font=('等线', 10), width=20, height=2)
lb_pj3.place(height=25, width=85, relx=0.78, rely=0.48)
ety_pj3 = Entry()
ety_pj3.place(height=15, width=35, relx=0.89, rely=0.489)
ety_pj3.insert(0, '20')
lb_pj4 = Label(root, text='团队协作:', font=('等线', 10), width=20, height=2)
lb_pj4.place(height=25, width=85, relx=0.78, rely=0.52)
ety_pj4 = Entry()
ety_pj4.place(height=15, width=35, relx=0.89, rely=0.529)
ety_pj4.insert(0, '20')
lb_pj5 = Label(root, text='社会责任:', font=('等线', 10), width=20, height=2)
lb_pj5.place(height=25, width=85, relx=0.78, rely=0.56)
ety_pj5 = Entry()
ety_pj5.place(height=15, width=35, relx=0.89, rely=0.569)
ety_pj5.insert(0, '20')
root.mainloop()
def change_page(type):
global page_index
if type == 1:
page_index = 2
lb_pj.configure(text='心理素质评价')
lb_pj1.configure(text='身体素质')
lb_pj2.configure(text='乐观情绪')
lb_pj3.configure(text='适应能力')
lb_pj4.configure(text='自律能力')
lb_pj5.configure(text='心理承受能力')
ety_pj1.delete(0, 'end')
ety_pj1.insert(0, '20')
ety_pj2.delete(0, 'end')
ety_pj2.insert(0, '20')
ety_pj3.delete(0, 'end')
ety_pj3.insert(0, '20')
ety_pj4.delete(0, 'end')
ety_pj4.insert(0, '20')
ety_pj5.delete(0, 'end')
ety_pj5.insert(0, '20')
else:
page_index = 1
lb_pj.configure(text='品德素质评价')
lb_pj1.configure(text='政治素养')
lb_pj2.configure(text='法制观念')
lb_pj3.configure(text='诚实守信')
lb_pj4.configure(text='团队协作')
lb_pj5.configure(text='社会责任')
ety_pj1.delete(0, 'end')
ety_pj1.insert(0, '20')
ety_pj2.delete(0, 'end')
ety_pj2.insert(0, '20')
ety_pj3.delete(0, 'end')
ety_pj3.insert(0, '20')
ety_pj4.delete(0, 'end')
ety_pj4.insert(0, '20')
ety_pj5.delete(0, 'end')
ety_pj5.insert(0, '20')
lb_error.configure(text='正在测评中...')
winNew = Toplevel(root)
winNew.geometry('480x940')
winNew.title('评分信息')
btStart = Button(winNew, text='继续填写', command=winNew.destroy)
btStart.place(relx=0.01, rely=0.01)
LstLable = Label(winNew, relief=RAISED, )
LstLable.place(relx=0.3)
Lstbox = Listbox(LstLable, width='45', height='40')
Lstbox.pack()
三、完整的代码
# -*- coding: utf-8 -*-
# @Time : 2022/8/4 22:31
# @Author : 小泽不偷懒
# @File : tkinter之学生互评.py
from tkinter import *
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
import tkinter.messagebox
page_index = 1
def change_page(type):
global page_index
if type == 1:
page_index = 2
lb_pj.configure(text='心理素质评价')
lb_pj1.configure(text='身体素质')
lb_pj2.configure(text='乐观情绪')
lb_pj3.configure(text='适应能力')
lb_pj4.configure(text='自律能力')
lb_pj5.configure(text='心理承受能力')
ety_pj1.delete(0, 'end')
ety_pj1.insert(0, '20')
ety_pj2.delete(0, 'end')
ety_pj2.insert(0, '20')
ety_pj3.delete(0, 'end')
ety_pj3.insert(0, '20')
ety_pj4.delete(0, 'end')
ety_pj4.insert(0, '20')
ety_pj5.delete(0, 'end')
ety_pj5.insert(0, '20')
else:
page_index = 1
lb_pj.configure(text='品德素质评价')
lb_pj1.configure(text='政治素养')
lb_pj2.configure(text='法制观念')
lb_pj3.configure(text='诚实守信')
lb_pj4.configure(text='团队协作')
lb_pj5.configure(text='社会责任')
ety_pj1.delete(0, 'end')
ety_pj1.insert(0, '20')
ety_pj2.delete(0, 'end')
ety_pj2.insert(0, '20')
ety_pj3.delete(0, 'end')
ety_pj3.insert(0, '20')
ety_pj4.delete(0, 'end')
ety_pj4.insert(0, '20')
ety_pj5.delete(0, 'end')
ety_pj5.insert(0, '20')
def spider_1():
# 第一级:学校登录界面结构不变,可直接抓包下一级网址,不需要进行数据解析,故不做处理
requests.packages.urllib3.disable_warnings() # 以防网站需要验证证书
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36 Edg/103.0.1264.71'
}
url = 'https://xssw.zjgsu.edu.cn/#/login'
session = requests.session()
# 第二级:赋值参数负载,进行登录,目前验证码不进行校对,故可省略,并需存储登录cookie
second_url = 'https://xssw.zjgsu.edu.cn/api/v1/login'
data = {
'password': ety_mm.get(),
'unionid': 'null',
'xgh': ety_zh.get(),
}
second_page_json = session.post(url=second_url, headers=headers, data=data).json()
if second_page_json['errorCode'] == 40101:
tkinter.messagebox.showerror('登录失败', '你的账号或密码输入错误!')
return
else:
tkinter.messagebox.showinfo('登录成功', '登录成功!!')
session.cookies['token'] = second_page_json['data']['access_token']
# 第三级:对测评详情页面发起get请求,获得json响应,以供后面逐个提交请求
third_url = 'https://xssw.zjgsu.edu.cn/api/v1/home/complex/evaluate/getGroupList?set_id=180&type=1'
third_page_json = session.get(url=third_url, headers=headers).json()
# 第四级:对每个学生进行post测评请求
# -测试是否在测评时间内
in_data = {"option1": 1, "option2": 1, "option3": 1,
"option4": 1, "option5": 1, "set_id": "121",
"type": 1,
"xgh": 'xxx'}
fourth_url = 'https://xssw.zjgsu.edu.cn/api/v1/home/complex/evaluate/group'
fourth_url_json = session.post(url=fourth_url, headers=headers, json=in_data).json()
if fourth_url_json['message'] == '不在开放时间内':
lb_error.configure(text='当前时间不在开放时间段内!')
# -获取数据并发送请求,并生成复选框
CheckVar = []
stu = []
stu_name = []
student_amount = 0
stu_xy = 0
for it in third_page_json['data']:
stu_xy += 1
CheckVar.append(IntVar())
CheckVar[student_amount].set(1)
stu_name.append(it['xm'])
stu.append(Checkbutton(root, text=it['xm'], variable=CheckVar[student_amount]))
stu[student_amount].place(height=20, width=65, relx=0.01 + (stu_xy - 1) // 5 * 0.1,
rely=0.45 + (stu_xy - 1) % 5 * 0.1)
student_amount += 1
btn_pf2 = Button(root, text='开始评分', font='等线', relief=RAISED,
command=lambda: spider_3(CheckVar, stu_name))
btn_pf2.place(height=28, width=120, relx=0.8, rely=0.68)
def spider_2():
lb_error.configure(text='正在测评中...')
winNew = Toplevel(root)
winNew.geometry('480x940')
winNew.title('评分信息')
btStart = Button(winNew, text='继续填写', command=winNew.destroy)
btStart.place(relx=0.01, rely=0.01)
LstLable = Label(winNew, relief=RAISED, )
LstLable.place(relx=0.3)
Lstbox = Listbox(LstLable, width='45', height='40')
Lstbox.pack()
requests.packages.urllib3.disable_warnings() # 以防网站需要验证证书
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36 Edg/103.0.1264.71'
}
session = requests.session()
second_url = 'https://xssw.zjgsu.edu.cn/api/v1/login'
data = {
'password': ety_mm.get(),
'unionid': 'null',
'xgh': ety_zh.get(),
}
second_page_json = session.post(url=second_url, headers=headers, data=data).json()
if second_page_json['errorCode'] == 40101:
tkinter.messagebox.showerror('登录失败', '你的账号或密码输入错误!')
return
else:
tkinter.messagebox.showinfo('登录成功', '登录成功!!')
session.cookies['token'] = second_page_json['data']['access_token']
third_url = 'https://xssw.zjgsu.edu.cn/api/v1/home/complex/evaluate/getGroupList?set_id=180&type=1'
third_page_json = session.get(url=third_url, headers=headers).json()
in_data = {"option1": 1, "option2": 1, "option3": 1,
"option4": 1, "option5": 1, "set_id": "121",
"type": 1,
"xgh": 'xxx'}
fourth_url = 'https://xssw.zjgsu.edu.cn/api/v1/home/complex/evaluate/group'
fourth_url_json = session.post(url=fourth_url, headers=headers, json=in_data).json()
if fourth_url_json['message'] == '不在开放时间内':
lb_error.configure(text='当前时间不在开放时间段内!')
student_amount = 0
for it in third_page_json['data']:
for i in [1, 2]:
in_data = {"option1": 20, "option2": 20, "option3": 20,
"option4": 20, "option5": 20, "set_id": "121",
"type": i,
"xgh": it['xgh']}
session.post(url=fourth_url, headers=headers, json=in_data).json()
if i == 1:
Type = '品德素质'
else:
Type = '心理素质'
Lstbox.insert('end','学生{}:{} {} 评分为:100 完成测评!'.format(student_amount + 1, it['xm'], Type))
student_amount += 1
Lstbox.insert('end','你对每位学生的评分为{} 共{}位学生测评成功!'.format(100, student_amount))
lb_error.configure(text='测评结束!')
def spider_3(CheckVar, stu_name):
lb_error.configure(text='正在测评中...')
winNew = Toplevel(root)
winNew.geometry('480x940')
winNew.title('评分信息')
btStart = Button(winNew, text='继续填写', command=winNew.destroy)
btStart.place(relx=0.01, rely=0.01)
LstLable = Label(winNew, relief=RAISED, )
LstLable.place(relx=0.3)
Lstbox = Listbox(LstLable, width='45', height='40')
Lstbox.pack()
# 第一级:学校登录界面结构不变,可直接抓包下一级网址,不需要进行数据解析,故不做处理
requests.packages.urllib3.disable_warnings() # 以防网站需要验证证书
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36 Edg/103.0.1264.71'
}
session = requests.session()
# 第二级:赋值参数负载,进行登录,目前验证码不进行校对,故可省略,并需存储登录cookie
second_url = 'https://xssw.zjgsu.edu.cn/api/v1/login'
data = {
'password': ety_mm.get(),
'unionid': 'null',
'xgh': ety_zh.get(),
}
second_page_json = session.post(url=second_url, headers=headers, data=data).json()
session.cookies['token'] = second_page_json['data']['access_token']
# 第三级:对测评详情页面发起get请求,获得json响应,以供后面逐个提交请求
third_url = 'https://xssw.zjgsu.edu.cn/api/v1/home/complex/evaluate/getGroupList?set_id=180&type=1'
third_page_json = session.get(url=third_url, headers=headers).json()
fourth_url = 'https://xssw.zjgsu.edu.cn/api/v1/home/complex/evaluate/group'
student_amount = 0
student_index = 0
total_score = 0
for it in third_page_json['data']:
if CheckVar[student_index].get():
if page_index == 1:
Type = '品德素质'
else:
Type = '心理素质'
if stu_name[student_index].split('已完成测评')[0] == Type:
print(it['xm'] + stu_name[student_index])
else:
in_data = {"option1": int(ety_pj1.get()), "option2": int(ety_pj2.get()), "option3": int(ety_pj3.get()),
"option4": int(ety_pj4.get()), "option5": int(ety_pj5.get()), "set_id": "121",
"type": page_index,
"xgh": it['xgh']}
session.post(url=fourth_url, headers=headers, json=in_data).json()
total_score = int(ety_pj1.get()) + int(ety_pj2.get()) + int(ety_pj3.get()) + int(ety_pj4.get()) + int(
ety_pj5.get())
Lstbox.insert('end',
'学生{}:{} {} 评分为:{} 完成测评!'.format(student_amount + 1, it['xm'], Type, total_score))
stu_name[student_index] = Type + '已完成测评'
student_amount += 1
student_index += 1
Lstbox.insert('end','你对每位学生的评分为{} 共{}位学生测评成功!'.format(total_score, student_amount))
lb_error.configure(text='测评结束!')
if __name__ == '__main__':
root = Tk()
root.title('浙商大学生事务管理平台自动填写互评 by:小泽不偷懒')
root.geometry('880x580')
lb_zh = Label(root, text='学号:', font=('等线', 20), width=20, height=2)
lb_zh.place(height=50, width=85, relx=0.2, rely=0.2)
ety_zh = Entry()
ety_zh.place(height=25, width=265, relx=0.3, rely=0.22)
lb_mm = Label(root, text='密码:', font=('等线', 20), width=20, height=2)
lb_mm.place(height=50, width=85, relx=0.2, rely=0.3)
ety_mm = Entry(show='*')
ety_mm.place(height=25, width=265, relx=0.3, rely=0.32)
lb_error = Label(root, text='请输入学号与密码后进行操作!', font=('等线', 15), width=20, height=2, fg='red')
lb_error.place(height=20, width=280, relx=0.31, rely=0.38)
btn_pf1 = Button(root, text='具体评分', font='等线', relief=RAISED,
command=lambda: spider_1())
btn_pf1.place(height=28, width=120, relx=0.62, rely=0.22)
btn_pf2 = Button(root, text='全部满分评分', font='等线', relief=RAISED,
command=lambda: spider_2())
btn_pf2.place(height=28, width=120, relx=0.62, rely=0.32)
# 评分各小项
lb_pj = Label(root, text='品德素质评价', font=('等线', 12), width=20, height=2)
lb_pj.place(height=25, width=95, relx=0.79, rely=0.35)
btn = Button(root, text='切换', font=('等线', 10), relief=RAISED, command=lambda: change_page(page_index))
btn.place(height=23, width=39, relx=0.92, rely=0.35)
lb_pj1 = Label(root, text='政治素养:', font=('等线', 10), width=20, height=2)
lb_pj1.place(height=25, width=85, relx=0.78, rely=0.4)
ety_pj1 = Entry()
ety_pj1.place(height=15, width=35, relx=0.89, rely=0.409)
ety_pj1.insert(0, '20')
lb_pj2 = Label(root, text='法制观念:', font=('等线', 10), width=20, height=2)
lb_pj2.place(height=25, width=85, relx=0.78, rely=0.44)
ety_pj2 = Entry()
ety_pj2.place(height=15, width=35, relx=0.89, rely=0.449)
ety_pj2.insert(0, '20')
lb_pj3 = Label(root, text='诚实守信:', font=('等线', 10), width=20, height=2)
lb_pj3.place(height=25, width=85, relx=0.78, rely=0.48)
ety_pj3 = Entry()
ety_pj3.place(height=15, width=35, relx=0.89, rely=0.489)
ety_pj3.insert(0, '20')
lb_pj4 = Label(root, text='团队协作:', font=('等线', 10), width=20, height=2)
lb_pj4.place(height=25, width=85, relx=0.78, rely=0.52)
ety_pj4 = Entry()
ety_pj4.place(height=15, width=35, relx=0.89, rely=0.529)
ety_pj4.insert(0, '20')
lb_pj5 = Label(root, text='社会责任:', font=('等线', 10), width=20, height=2)
lb_pj5.place(height=25, width=85, relx=0.78, rely=0.56)
ety_pj5 = Entry()
ety_pj5.place(height=15, width=35, relx=0.89, rely=0.569)
ety_pj5.insert(0, '20')
root.mainloop()
总结
虽然程序和界面做的都还是挺粗糙的,整个底层逻辑可能看起来有点让人贻笑大方了。有点像是为了可视化而进行一些可视化操作。涉及到用户交互,其实还有很多地方和想法我都没有实现,主要是感觉差不多了哈哈哈。
不管怎么说最后的成品个人还算是比较满意的,自己也花了一点心思到用户交互体验上,说到这个用户交互真是想想就头疼,可能一个偏习惯化的行为你就得为此大改程序。