自动录课项目

本项目由作者独自完成

技术栈:Python,PyQt,爬虫

起因:实训中心的手动录课实在是效率低下,浪费时间,本作者实在是受不了啦(吐槽)

故开发了这个小软件,用于实现自动录课,避免每次录课浪费人生中宝贵的十几分钟和录错事件

505的学弟学妹请看这里

  • 如果你也是实训中心的学弟学妹可以看看软件的实现逻辑,我毕业之后就连不上校园网登录实训中心账户进行维护啦,如果教务网和教室管理平台后续有更新,则可能导致该软件不可用,可根据更新的参数对代码进行修改

我将在毕业前尽可能完善软件

注意

为了防止泄露,代码中不展示一些URL,在505电脑中可查看

开发日志

2024.12.10
本项目于2024年12月10号20:30开始立项
尝试利用程序进行登录->失败
结论:学艺不精->回炉重造

2024.12.12
学成归来,利用cookie获取借用信息,跳过登录环节
获取到借用信息要用到的参数,成功获取到借用的html信息,成功筛选出教室名称和借用时间
获取到录用教室要用到的参数,完成录用模块,测试成功
今天到此结束—2024.12.13,00:37
明天将借用信息和录用模块结合

2024.12.13
将借用信息和录用模块结合

2024.12.14
英语四六级上班

2024.12.15
将代码进行整理,转化成类实现
完成菜单功能
完成终端实现
版本—1.0.0

2024.12.16
第一次测试,发现bug,无法录入教室管理平台
bug:传入负载时的教室id错误(已修复)
第二次测试,成功

2024.12.17
设计登录界面ui

2024.12.19
完成主界面设计
完成系统登录接口和登录界面的连接

2024.12.21
完成所有主界面接口对接,修改部分源代码
对所有代码进行整合优化加注释
进行第一次测试
发现录入日期有问题:教务网17周星期日的借用内容在录课平台应该是16周星期日(已修复)

第二次测试无问题
打包成自动录课系统exe__2.0.1版本

2024.12.24
23号晚上在办公室电脑发现软件无法使用,猜测有兼容问题
优化了打包方式,win10电脑可以使用
win7电脑由于本人要复习期末周,暂时搁置(有时间再搞吧~)

发现点击登录按钮之后软件闪退
原因:粘贴cookie时有时候会在前面有空格,在访问教务网获取数据时,传入的参数错误导致闪退
作者暂时未修复,因为比较忙,先标记

终端版

没有ui的版本,基本可避免各种兼容问题,只要在Python终端运行即可(注意库一致)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
import re
from time import sleep

import requests
from bs4 import BeautifulSoup
from datetime import datetime, timedelta
import time

#根据周和星期获取日期的类
class WeekDateCalculator:
def __init__(self, start_year, start_month, start_day):
"""
初始化类,设置第一周的星期日的日期
:param start_year: 年份
:param start_month: 月份
:param start_day: 日期
"""
self.start_date = datetime(start_year, start_month, start_day)
# 确保start_date是星期日
while self.start_date.weekday() != 6: # 星期日对应的weekday()值是6
self.start_date += timedelta(days=1)

def get_date_by_week_and_day(self, week_number, day_of_week):
"""
根据周数和星期几获取日期
:param week_number: 周数(从第一周开始)
:param day_of_week: 星期几(0代表星期一,1代表星期二,...,6代表星期日)
:return: 对应日期的datetime对象
"""
# 计算从第一周星期日到目标星期几的天数偏移
target_day_offset = (day_of_week - self.start_date.weekday() + 7) % 7
# 计算目标日期与第一周星期日之间的总天数
total_days = (week_number - 1) * 7 + target_day_offset
# 计算目标日期
target_date = self.start_date + timedelta(days=total_days)
return target_date

#录课系统登录类
class dl :
#登录页面
#判断是否登录成功,成功则返回会话对象
def cdym__ff(self):
while 1:
print("欢迎使用自动录课系统")
cookie2 = input("请输入录课会话秘钥:")
B =self.lk(cookie2)
if"state"in B.text:
print("登录成功")
break
else:
print("登录失败,请检查秘钥")

while 1:
cookie =input("请输入登录会话秘钥:")
A = dl.dl_ff(cookie)
if "用户没有登录,请重新登录" in A.text:
print("登录失败")
elif"您登录后过长时间没有操作或您的用户名已经在别处登录!"in A.text:
print("您登录后过长时间没有操作或您的用户名已经在别处登录,请重新获取cookie")
elif "教室" in A.text:
print("登录成功")
break

return cookie,cookie2

# 录课模块,用于被录课方法引用
# 录课数据
def lk(self,cookie2):
data = {
'room_id': 1, # 教室id 1需要
'room_name': "1-301", # 教室名称 1需要
'year': '2024', # 年
'term': '1', # 学期
'term_start': '2024-09-02', # 学期开头日期
'week_no': 20, # 周 需要
'weekday': 1, # 星期 需要
'section': 1, # 从哪小节进入录课界面 1需要
'start_section': 1, # 录课的开始节 1需要
'end_section': 2, # 录课的结束节 2需要
'people_id': '0001130071', # 老师id
'audience': '借用', # 两个填的地方
'reason': '借用'
}
url = "录课平台URL,防止泄露,故不展示,505电脑中有此记载"
A = requests.post(url, data=data, headers={"cookie": f"{cookie2}"})#获取数据
return A


# 返回登录对象
def dl_ff(self,cookie):
data2 = {
"gnq_mh": "",
"jsmc_mh": "",
"typewhere": "jwyx",
"xnxqh": "2024-2025-1", # 学期
"xqbh": "2", # 校区,白云
"jxqbh": "CBD7DE758E094061AE21E96B1B32CC56", # 教学区:多媒体
"jslx": "", # 教室类型
"jxlbh": "", # 教学楼
"jsbh": "", # 教室
"bjfh": "=", # 人数
"rnrs": "", # 人数空白
"jszt": "2", # 借用,1是正常上课,2是借用,3是锁定,4是考试,5是空闲....
"yx": "", # 借用院系
"zc": 1, # 周次1 1需要
"zc2": 1, # 周次2 1需要
"xq": 1, # 星期1 1需要
"xq2": 1, # 星期2 1需要
"jc": "01", # 节次1
"jc2": "11", # 节次2
"kbjcmsid": "29637FA5710B46F3B01242A09D7E9CCD", # 时间模式,白云
"qsrq": "2024-09-01", # 日期 1需要
"jsrq": "2024-09-01", # 日期 1需要
"ssdw": "" # 教室所属单位
}
url = ("教务网对应URL,防止泄露,故不展示,505电脑中有此记载")
A = requests.post(url, data=data2, headers={"cookie": f"{cookie}"})
return A

#获取 周次 星期 查询节次1 查询节次2 日期
def sj_hq(self):
zc_ =input("周次:")
xq_=input("星期:")
jc1_=1#input("查询节次1:")
jc2_=11#input("查询节次2:")
#设置开学日期
calculator = WeekDateCalculator(2024, 9, 1) # 根据实际情况设置年份、月份和日期
#设置周次和星期
week_number = int(zc_)
day_of_week = int(xq_)-1
#获取日期
result_date = calculator.get_date_by_week_and_day(week_number, day_of_week)
rq_ =result_date.strftime('%Y-%m-%d')

#返回 周次 星期 查询节次1 查询节次2 日期
return zc_,xq_,jc1_,jc2_,rq_

#自动录课系统
class luke:
# 定义各种参数
zc = 0 # 周次
xq = 0 # 星期
jc1 = 1 # 查询节次1
jc2 = 2 # 查询节次2
rq = "2024-12-09" # 日期
# #教室id
id = []
# 教室名称
js_name = ""
cookie =""
cookie2 = ""

# 初始化查询的
def __init__(self, zc_, xq_, jc1_, jc2_, rq_,cookie_1,cookie_2):
self.zc = zc_ # 周次
self.xq = xq_ # 星期
self.jc1 = jc1_ # 查询节次1
self.jc2 = jc2_ # 查询节次2
self.rq = rq_ # 日期
self.cookie =cookie_1 #登录秘钥
self.cookie2 = cookie_2 # 录课秘钥

#查询数据,获取html,返回html
def cx(self):
data2 ={
"gnq_mh":"" ,
"jsmc_mh":"",
"typewhere": "jwyx",
"xnxqh": "2024-2025-1",#学期
"xqbh": "2",#校区,白云
"jxqbh": "CBD7DE758E094061AE21E96B1B32CC56",#教学区:多媒体
"jslx":"",#教室类型
"jxlbh":"",#教学楼
"jsbh":"",#教室
"bjfh":"=",#人数
"rnrs":"",#人数空白
"jszt":"2",#借用,1是正常上课,2是借用,3是锁定,4是考试,5是空闲....
"yx":"",#借用院系
"zc": self.zc,#周次1 1需要
"zc2": self.zc,#周次2 1需要
"xq": self.xq,#星期1 1需要
"xq2": self.xq,#星期2 1需要
"jc": self.jc1,#节次1
"jc2": self.jc2,#节次2
"kbjcmsid": "29637FA5710B46F3B01242A09D7E9CCD",#时间模式,白云
"qsrq": self.rq,#日期 1需要
"jsrq": self.rq,#日期 1需要
"ssdw":""#教室所属单位
}
url =("教务网对应URL,防止泄露,故不展示,505电脑中有此记载")
A =requests.post(url,data= data2, headers={"cookie":f"{self.cookie}"})
return A

#获取借用清单
def qd(self,A):
B = BeautifulSoup(A.text,"html.parser")
C=B.find("table",attrs={"id":"kbtable"})#获取总表格
D =C.find("tbody")#获取没有标题的表格
C =D.find_all("tr")#获取每间教室

# #总借用清单
jyqd=[]
#获取总借用清单,格式[[['1-302'], 0, 1, 0, 0, 1, 1], [['1-406'], 0, 0, 0, 1, 1, 0]]
#0表示没有借用,1表示借用
for i in C:
#大节
sj =0
#获取查询大节次数
xj =int(self.jc2)-int(self.jc2)

# 教室借用清单
jyqd2 = []
for a in i.find_all_next("td"):#一个教室的每个时间段
if sj==0:#获取教室名称
A=re.findall("\d-\d{3}",a.text)
#print(sj,A)
jyqd2.append(A)
sj=sj+1
elif sj<7:#获取1-6大节借用情况
A = re.findall("J", a.text)#查看
#print(sj, A)
if A ==["J"]:
jyqd2.append(1)
else:
jyqd2.append(0)
sj = sj + 1

jyqd.append(jyqd2)
# 循环输出借用每个教室清单
#print(jyqd2)
#输出借用总清单
#print(jyqd)
#教室数量
#print(len(jyqd))
#获取教室名称
T=[]
for i in range(len(jyqd)):
T.append(jyqd[i][0])
return jyqd,len(T),T

#录用开始结束小节换算
def hs (self,a):
if a==1:
return 1,2
elif a==2:
return 3,4
elif a==3:
return 5,6
elif a==4:
return 7,8
elif a==5:
return 9,10
elif a==6:
return 11,11
#录课方法
def luk(self,QD,SL,MC):#借用总清单,教室数量,教室名称
#教室名称对应的id字典
js_id ={'1-301': '1', '1-302': '2', '1-303': '3', '1-305': '4', '1-311': '5', '1-312': '6', '1-313': '7', '1-314': '8', '1-315': '9', '1-405': '10', '1-406': '11', '1-407': '12', '1-408': '13', '1-409': '14', '1-410': '15', '1-411': '16', '1-412': '17', '1-413': '18', '1-414': '19', '1-415': '20', '1-416': '21', '1-417': '22', '1-418': '23', '1-419': '24', '1-420': '25', '1-506': '26', '1-507': '27', '1-508': '28', '1-509': '29', '1-510': '30', '1-511': '31', '1-512': '32', '1-513': '33', '1-514': '34', '1-515': '35', '1-516': '36', '1-517': '37', '1-518': '38', '1-519': '39', '1-520': '40', '1-602': '41', '1-603': '42', '1-604': '43', '1-605': '44', '1-606': '45', '1-607': '46', '1-608': '47', '1-609': '48', '1-610': '49', '1-611': '50', '1-612': '51', '1-613': '52', '1-614': '53', '1-615': '54', '1-616': '55', '1-617': '56', '1-618': '57', '1-619': '58', '1-703': '59', '1-704': '60', '1-705': '61', '1-706': '62', '1-707': '63', '1-708': '64', '1-709': '65', '1-710': '66', '1-711': '67', '1-713': '68', '1-714': '69', '1-715': '70', '1-716': '71', '1-717': '72', '1-718': '73', '1-719': '74', '1-720': '75', '1-721': '76', '1-722': '77', '2-101': '78', '2-102': '79', '2-103': '80', '2-104': '81', '2-201': '82', '2-202': '83', '2-203': '84', '2-204': '85','2-301': '86', '2-302': '87', '2-303': '88', '2-304': '89', '2-305': '90', '2-306': '91', '2-401': '92', '2-402': '93', '2-403': '94', '2-404': '95', '2-501': '96', '2-502': '97', '2-503': '98', '2-504': '99', '2-601': '100', '2-602': '101', '2-603': '102', '2-604': '103', '2-701': '104', '2-702': '105', '2-703': '106', '2-704': '107'}
#获取单间教室名称以及id,并录课
id_=0
for i in range(SL):
A =MC[i]
C=str(A).strip("['")
C=C.strip("']")#教室名称
self.id.append(js_id[C])#教室名称对应id

for i in QD: # 获取每间教室借用信息
for a in range(1, 7): # 检查教室哪节有借用,有则录入
if i[a] == 0:
# print(f"第{a}大节没有借用")
pass
elif i[a] == 1:
ks, js = self.hs(a) # 获取开始结束小节
#print(f"{i[0]}第{ks,js}小节有借用", self.id[id_])
print(self.id[id_],i[0],self.zc,self.xq,ks,js)
self.lk(self.id[id_],i[0],self.zc,self.xq,ks,js)

id_ = id_ + 1
sleep(0.1)

#录课模块,用于被录课方法引用
# 录课数据
def lk(self,id,name,zc,xq,ks,js):
data ={
'room_id': id,#教室id 1需要
'room_name':name,#教室名称 1需要
'year': '2024',#年
'term': '1',#学期
'term_start': '2024-09-02',#学期开头日期
'week_no': zc,#周 需要
'weekday': xq,#星期 需要
'section': ks,#从哪小节进入录课界面 1需要
'start_section': ks,#录课的开始节 1需要
'end_section': js,#录课的结束节 2需要
'people_id': '0001130071',#老师id
'audience': '借用',#两个填的地方
'reason': '借用'
}
url = "录课平台对应URL,防止泄露,故不展示,505电脑中有此记载"
A =requests.post(url,data=data,headers={"cookie":f"{self.cookie2}"})
if "state" in A.text:
print("入录成功")



if __name__=="__main__":
#实例登录对象
dl =dl()
#获取登录成功的cookie
cookie,cookie2 =dl.cdym__ff()
QD=[]
SL =0
MC =[]
#菜单
while True:
print(" 欢迎使用自动录课系统")
print("*******************")
print("*———————功能———————*")
print("*1.查询借用清单 *")
print("*2.录入查询的清单 *")
print("*3.退出 *")
print("*******************")
a =input()
if a == "1":
# 获取想查询的数据
zc, xq, jc1, jc2, rq = dl.sj_hq()
print(zc, xq, jc1, jc2, rq)
# 实例一个自动录课系统类的对象
luke = luke(zc, xq, jc1, jc2, rq, cookie, cookie2)
A = luke.cx()#获取查询到的html
QD, SL, MC = luke.qd(A) # 返回借用清单,借用数量,借用教室名称
print(f"借用教室数量:{SL}")
for a in QD:
print(a)
#print(f"有借用的教室名称{MC}")

elif a=="2":
luke.luk(QD, SL, MC)
elif a == "3":
break
else:
print("请输入对应功能的数字,如:1")








软件版

使用qt作为UI,并且打包

登录界面的UI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>946</width>
<height>501</height>
</rect>
</property>
<property name="windowTitle">
<string>自动录课平台</string>
</property>
<property name="windowIcon">
<iconset>
<normaloff>D:/C++笔记/python/favicon.ico</normaloff>D:/C++笔记/python/favicon.ico</iconset>
</property>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>60</x>
<y>110</y>
<width>261</width>
<height>51</height>
</rect>
</property>
<property name="font">
<font>
<family>微软雅黑</family>
<pointsize>26</pointsize>
</font>
</property>
<property name="text">
<string>自动录课系统</string>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>28</x>
<y>210</y>
<width>161</width>
<height>31</height>
</rect>
</property>
<property name="font">
<font>
<family>微软雅黑</family>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>录课平台cookie:</string>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>28</x>
<y>240</y>
<width>161</width>
<height>41</height>
</rect>
</property>
<property name="font">
<font>
<family>微软雅黑</family>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>教务平台cookie:</string>
</property>
</widget>
<widget class="QLineEdit" name="jw_cookie">
<property name="geometry">
<rect>
<x>180</x>
<y>250</y>
<width>191</width>
<height>31</height>
</rect>
</property>
</widget>
<widget class="QLineEdit" name="luke_cookie">
<property name="geometry">
<rect>
<x>180</x>
<y>210</y>
<width>191</width>
<height>31</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="dl_bth">
<property name="geometry">
<rect>
<x>140</x>
<y>310</y>
<width>101</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>登录</string>
</property>
</widget>
<widget class="QTextEdit" name="textEdit">
<property name="geometry">
<rect>
<x>410</x>
<y>0</y>
<width>541</width>
<height>501</height>
</rect>
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'SimSun'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:18pt;&quot;&gt;欢迎使用自动录课系统&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;本系统由小楼夜听雨制作并提供维护&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;如果使用过程中出现bug,请停止使用并联系我&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;微信:19955181843&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;使用方法:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;1.点击查询按钮进入查询页面,选择周次和星期进行查询,查询结果正确则点击保存&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;2.点击录入按钮进入录入界面,点击查看模板按钮可查看已经保存的借用模版,显示教室数量等信息,确认无误后则点击录入,录入情况会显示录入完成情况&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;请按照步骤进行,跳过步骤进行可能出现意想不到的bug&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;注意:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;本系统只开发了录入一天借用的功能,并不具备自定义录入的功能(作者比较懒)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;每学年开始前,要在sj_hq方法中设置开学第一周的日期&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>

主界面UI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>916</width>
<height>543</height>
</rect>
</property>
<property name="windowTitle">
<string>自动录课平台</string>
</property>
<property name="windowIcon">
<iconset>
<normaloff>D:/C++笔记/python/favicon.ico</normaloff>D:/C++笔记/python/favicon.ico</iconset>
</property>
<widget class="QFrame" name="frame">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>121</width>
<height>521</height>
</rect>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<widget class="QPushButton" name="bth_cx">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>101</width>
<height>81</height>
</rect>
</property>
<property name="text">
<string>查询</string>
</property>
</widget>
<widget class="QPushButton" name="bth_lr">
<property name="geometry">
<rect>
<x>10</x>
<y>190</y>
<width>101</width>
<height>81</height>
</rect>
</property>
<property name="text">
<string>录入</string>
</property>
</widget>
<widget class="QPushButton" name="bth_tc">
<property name="geometry">
<rect>
<x>10</x>
<y>360</y>
<width>101</width>
<height>81</height>
</rect>
</property>
<property name="text">
<string>退出</string>
</property>
</widget>
</widget>
<widget class="QTabWidget" name="tabWidget_2">
<property name="geometry">
<rect>
<x>140</x>
<y>-30</y>
<width>791</width>
<height>581</height>
</rect>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab_cx">
<attribute name="title">
<string/>
</attribute>
<widget class="QComboBox" name="comboBox_zc">
<property name="geometry">
<rect>
<x>86</x>
<y>40</y>
<width>91</width>
<height>31</height>
</rect>
</property>
<item>
<property name="text">
<string>1</string>
</property>
</item>
<item>
<property name="text">
<string>2</string>
</property>
</item>
<item>
<property name="text">
<string>3</string>
</property>
</item>
<item>
<property name="text">
<string>4</string>
</property>
</item>
<item>
<property name="text">
<string>5</string>
</property>
</item>
<item>
<property name="text">
<string>6</string>
</property>
</item>
<item>
<property name="text">
<string>7</string>
</property>
</item>
<item>
<property name="text">
<string>8</string>
</property>
</item>
<item>
<property name="text">
<string>9</string>
</property>
</item>
<item>
<property name="text">
<string>10</string>
</property>
</item>
<item>
<property name="text">
<string>11</string>
</property>
</item>
<item>
<property name="text">
<string>12</string>
</property>
</item>
<item>
<property name="text">
<string>13</string>
</property>
</item>
<item>
<property name="text">
<string>14</string>
</property>
</item>
<item>
<property name="text">
<string>15</string>
</property>
</item>
<item>
<property name="text">
<string>16</string>
</property>
</item>
<item>
<property name="text">
<string>17</string>
</property>
</item>
<item>
<property name="text">
<string>18</string>
</property>
</item>
<item>
<property name="text">
<string>19</string>
</property>
</item>
<item>
<property name="text">
<string>20</string>
</property>
</item>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>20</x>
<y>30</y>
<width>81</width>
<height>41</height>
</rect>
</property>
<property name="font">
<font>
<family>微软雅黑</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>周次:</string>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>200</x>
<y>30</y>
<width>71</width>
<height>41</height>
</rect>
</property>
<property name="font">
<font>
<family>微软雅黑</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>星期:</string>
</property>
</widget>
<widget class="QComboBox" name="comboBox_xq">
<property name="geometry">
<rect>
<x>270</x>
<y>40</y>
<width>101</width>
<height>31</height>
</rect>
</property>
<item>
<property name="text">
<string>1</string>
</property>
</item>
<item>
<property name="text">
<string>2</string>
</property>
</item>
<item>
<property name="text">
<string>3</string>
</property>
</item>
<item>
<property name="text">
<string>4</string>
</property>
</item>
<item>
<property name="text">
<string>5</string>
</property>
</item>
<item>
<property name="text">
<string>6</string>
</property>
</item>
<item>
<property name="text">
<string>7</string>
</property>
</item>
</widget>
<widget class="QPushButton" name="bth_cx_cx">
<property name="geometry">
<rect>
<x>420</x>
<y>40</y>
<width>101</width>
<height>31</height>
</rect>
</property>
<property name="font">
<font>
<family>微软雅黑</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>查询</string>
</property>
</widget>
<widget class="QPushButton" name="bth_cx_bc">
<property name="geometry">
<rect>
<x>570</x>
<y>40</y>
<width>101</width>
<height>31</height>
</rect>
</property>
<property name="font">
<font>
<family>微软雅黑</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>保存</string>
</property>
</widget>
<widget class="QTextBrowser" name="textBrowser">
<property name="geometry">
<rect>
<x>-20</x>
<y>90</y>
<width>771</width>
<height>441</height>
</rect>
</property>
</widget>
</widget>
<widget class="QWidget" name="tab_lr">
<attribute name="title">
<string></string>
</attribute>
<widget class="QPushButton" name="pushButton_3">
<property name="geometry">
<rect>
<x>150</x>
<y>30</y>
<width>101</width>
<height>41</height>
</rect>
</property>
<property name="font">
<font>
<family>微软雅黑</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>查看模板</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_4">
<property name="geometry">
<rect>
<x>340</x>
<y>20</y>
<width>101</width>
<height>41</height>
</rect>
</property>
<property name="font">
<font>
<family>微软雅黑</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>录入平台</string>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>550</x>
<y>30</y>
<width>111</width>
<height>41</height>
</rect>
</property>
<property name="font">
<font>
<family>微软雅黑</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>录用情况</string>
</property>
</widget>
<widget class="QTextBrowser" name="textBrowser_2">
<property name="geometry">
<rect>
<x>20</x>
<y>80</y>
<width>411</width>
<height>451</height>
</rect>
</property>
</widget>
<widget class="QTextBrowser" name="textBrowser_3">
<property name="geometry">
<rect>
<x>430</x>
<y>80</y>
<width>341</width>
<height>451</height>
</rect>
</property>
</widget>
</widget>
</widget>
</widget>
<resources/>
<connections/>
</ui>

自动录课的py文件

头文件

1
2
3
4
5
import re
from time import sleep
import requests
from bs4 import BeautifulSoup
from datetime import datetime, timedelta

根据周和星期获取日期的类

初始化的时候需要输入学期第一周星期日的日期(注意:学校第一周的第一天是从星期日开始的),然后调用类的方法时输入周次和星期即可返回对应的日期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#根据周和星期获取日期的类
class WeekDateCalculator:
def __init__(self, start_year, start_month, start_day):
"""
初始化类,设置第一周的星期日的日期
:param start_year: 年份
:param start_month: 月份
:param start_day: 日期
"""
self.start_date = datetime(start_year, start_month, start_day)
# 确保start_date是星期日
while self.start_date.weekday() != 6: # 星期日对应的weekday()值是6
self.start_date += timedelta(days=1)

def get_date_by_week_and_day(self, week_number, day_of_week):
"""
根据周数和星期几获取日期
:param week_number: 周数(从第一周开始)
:param day_of_week: 星期几(0代表星期一,1代表星期二,...,6代表星期日)
:return: 对应日期的datetime对象
"""
# 计算从第一周星期日到目标星期几的天数偏移
target_day_offset = (day_of_week - self.start_date.weekday() + 7) % 7
# 计算目标日期与第一周星期日之间的总天数
total_days = (week_number - 1) * 7 + target_day_offset
# 计算目标日期
target_date = self.start_date + timedelta(days=total_days)
return target_date

录课系统登录类

该类的作用是提供在登录的时候的方法,包含两个静态变量

1
2
3
class dl :
cookie2 =None
cookie = None

判断是否登录成功的方法

登录页面判断是否登录成功,成功则返回两个cookie

登录失败则返回对应的错误数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def cdym__ff(self,jw_cookie,luke_cookie):
while 1:
self.cookie2 = luke_cookie
B =self.lk(self.cookie2)
if"state"in B.text:
print("登录成功1")
break
else:
print("登录失败,请检查秘钥")
return 1,0

while 1:
self.cookie =jw_cookie
A = self.dl_ff(self.cookie)
if "用户没有登录,请重新登录" in A.text:
print("登录失败")
return 2,0
elif"您登录后过长时间没有操作或您的用户名已经在别处登录!"in A.text:
print("您登录后过长时间没有操作或您的用户名已经在别处登录,请重新获取cookie")
return 3,0
elif "教室" in A.text:
print("登录成功2")
break

return self.cookie,self.cookie2

用于测试是否录课平台登录成功的方法

调用该方法会向录课平台发送一个录课请求(1-301第20周星期一1-2节)并返回结果,在上面判断是否登录成功的方法中进行判断是否登录成功

  • 注意:每个学期的开学日期可能会变,请每个学期第一次使用时查看参数是否一致(重点是学期开头日期和教室id),张老师4月份开始休假,需要更换为莫老师的id
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def lk(self,cookie2):
data = {
'room_id': 1, # 教室id 1需要
'room_name': "1-301", # 教室名称 1需要
'year': '2024', # 年
'term': '1', # 学期
'term_start': '2024-09-02', # 学期开头日期
'week_no': 20, # 周 需要
'weekday': 1, # 星期 需要
'section': 1, # 从哪小节进入录课界面 1需要
'start_section': 1, # 录课的开始节 1需要
'end_section': 2, # 录课的结束节 2需要
'people_id': '0001130071', # 老师id
'audience': '借用', # 两个填的地方
'reason': '借用'
}
url = "录课平台URL,防止泄露,故不展示,505电脑中有此记载"
A = requests.post(url, data=data, headers={"cookie": f"{cookie2}"})
return A

用于测试是否教务网登录成功的方法

调用该方法会向教务网发送一个借用信息查询请求并返回结果,在上面判断是否登录成功的方法中进行判断是否登录成功

  • 注意:每个学期需要该一下,请每个学期第一次使用时查看参数是否一致(重点是学期和日期)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def dl_ff(self,cookie):
data2 = {
"gnq_mh": "",
"jsmc_mh": "",
"typewhere": "jwyx",
"xnxqh": "2024-2025-1", # 学期
"xqbh": "2", # 校区,白云
"jxqbh": "CBD7DE758E094061AE21E96B1B32CC56", # 教学区:多媒体
"jslx": "", # 教室类型
"jxlbh": "", # 教学楼
"jsbh": "", # 教室
"bjfh": "=", # 人数
"rnrs": "", # 人数空白
"jszt": "2", # 借用,1是正常上课,2是借用,3是锁定,4是考试,5是空闲....
"yx": "", # 借用院系
"zc": 1, # 周次1
"zc2": 1, # 周次2
"xq": 1, # 星期1
"xq2": 1, # 星期2
"jc": "01", # 节次1
"jc2": "11", # 节次2
"kbjcmsid": "29637FA5710B46F3B01242A09D7E9CCD", # 时间模式,白云
"qsrq": "2024-09-01", # 日期
"jsrq": "2024-09-01", # 日期
"ssdw": "" # 教室所属单位
}
url = ("教务网URL,防止泄露,故不展示,505电脑中有此记载")
A = requests.post(url, data=data2, headers={"cookie": f"{cookie}"})
return A

获取 周次 星期 查询节次1 查询节次2 日期的方法

调用该方法需要传入周次和星期,然后会输出周次 星期 查询节次1 查询节次2 日期

用于为下面自动录课系统类的实例提供参数

  • 注意:每个学期开始需要设置开学的日期
  • 后面如果拓展自定义查询节次的功能可从此入手
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def sj_hq(self,zc,xq):
zc_ =zc
xq_=xq
jc1_=1#input("查询节次1:")
jc2_=11#input("查询节次2:")
#设置开学日期
calculator = WeekDateCalculator(2024, 9, 1) # 根据实际情况设置年份、月份和日期
#设置周次和星期
week_number = int(zc_)
day_of_week = int(xq_)-1
#获取日期
result_date = calculator.get_date_by_week_and_day(week_number, day_of_week)
rq_ =result_date.strftime('%Y-%m-%d')

#返回 周次 星期 查询节次1 查询节次2 日期
return zc_,xq_,jc1_,jc2_,rq_

自动录课系统类

这个类的作用是实现自动录课的逻辑,包含

  1. 向教务网获取借用数据的方法
  2. 将借用数据转化为参数的方法
  3. 将参数转化为录课平台所需要的录入节次的方法
  4. 将相关参数转化成合适的形式,并调用下面5的方法进行录课的方法
  5. 向录课平台发送录课数据进行录课的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
class luke:
# 定义各种参数
zc = 0 # 周次
xq = 0 # 星期
jc1 = 1 # 查询节次1
jc2 = 2 # 查询节次2
rq = "2024-12-09" # 日期
#借用教室的id列表
id = []
# 教室名称
js_name = ""
cookie =""
cookie2 = ""

该类的构造函数

1
2
3
4
5
6
7
8
9
# 初始化查询的
def __init__(self, zc_, xq_, jc1_, jc2_, rq_,cookie_1,cookie_2):
self.zc = zc_ # 周次
self.xq = xq_ # 星期
self.jc1 = jc1_ # 查询节次1
self.jc2 = jc2_ # 查询节次2
self.rq = rq_ # 日期
self.cookie =cookie_1 #登录秘钥
self.cookie2 = cookie_2 # 录课秘钥

向教务网获取借用数据的方法

该方法会使用该类实例时候传入的参数向教务网获取相关的html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
def cx(self):
data2 ={
"gnq_mh":"" ,
"jsmc_mh":"",
"typewhere": "jwyx",
"xnxqh": "2024-2025-1",#学期
"xqbh": "2",#校区,白云
"jxqbh": "CBD7DE758E094061AE21E96B1B32CC56",#教学区:多媒体
"jslx":"",#教室类型
"jxlbh":"",#教学楼
"jsbh":"",#教室
"bjfh":"=",#人数
"rnrs":"",#人数空白
"jszt":"2",#借用,1是正常上课,2是借用,3是锁定,4是考试,5是空闲....
"yx":"",#借用院系
"zc": self.zc,#周次1 1需要
"zc2": self.zc,#周次2 1需要
"xq": self.xq,#星期1 1需要
"xq2": self.xq,#星期2 1需要
"jc": self.jc1,#节次1
"jc2": self.jc2,#节次2
"kbjcmsid": "29637FA5710B46F3B01242A09D7E9CCD",#时间模式,白云
"qsrq": self.rq,#日期 1需要
"jsrq": self.rq,#日期 1需要
"ssdw":""#教室所属单位
}
url =("教务网URL,防止泄露,故不展示,505电脑中有此记载")
A =requests.post(url,data= data2, headers={"cookie":f"{self.cookie}"})
#print(A.text)
return A

将借用数据转化为参数的方法

该方法需要传入html,可以从html文件中获取到有借用的教室及其借用的时间段记录到列表

会返回借用的总清单列表,总借用教室数量,借用教室

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
def qd(self,A):
B = BeautifulSoup(A.text,"html.parser")
C=B.find("table",attrs={"id":"kbtable"})#获取总表格
D =C.find("tbody")#获取没有标题的表格
C =D.find_all("tr")#获取每间教室

# #总借用清单
jyqd=[]
#获取总借用清单,格式[[['1-302'], 0, 1, 0, 0, 1, 1], [['1-406'], 0, 0, 0, 1, 1, 0]]
#0表示没有借用,1表示借用
for i in C:
#大节
sj =0
#获取查询大节次数
xj =int(self.jc2)-int(self.jc2)

# 一个教室借用清单
jyqd2 = []
for a in i.find_all_next("td"):#一个教室的每个时间段
if sj==0:#获取教室名称
A=re.findall("\d-\d{3}",a.text)
#print(sj,A)
jyqd2.append(A)
sj=sj+1
elif sj<7:#获取1-6大节借用情况
A = re.findall("J", a.text)#查看
#print(sj, A)
if A ==["J"]:
jyqd2.append(1)
else:
jyqd2.append(0)
sj = sj + 1

将一间教室的清单添加到总清单
jyqd.append(jyqd2)
# 循环输出借用每个教室清单
#print(jyqd2)
#输出借用总清单
#print(jyqd)
#输出教室数量
#print(len(jyqd))
#获取教室名称
T=[]
for i in range(len(jyqd)):
T.append(jyqd[i][0])
return jyqd,len(T),T

将参数转化为录课平台所需要的录入节次的方法

该方法用于在下面向录课平台发送录课数据进行录课的方法中判断借用的节次,并返回相应的节次

1
2
3
4
5
6
7
8
9
10
11
12
13
def hs (self,a):
if a==1:
return 1,2
elif a==2:
return 3,4
elif a==3:
return 5,6
elif a==4:
return 7,8
elif a==5:
return 9,10
elif a==6:
return 11,11

将相关参数转化成合适的形式,并调用下面5的方法进行录课的方法

该方法需要传入总清单,教室数量,教室名称,周次,星期

方法会将这些参数进行处理,并调用录课方法进行录课

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def luk(self,QD,SL,MC,zc,xq):#借用总清单,教室数量,教室名称
#教室名称对应的id字典
js_id ={'1-301': '1', '1-302': '2', '1-303': '3', '1-305': '4', '1-311': '5', '1-312': '6', '1-313': '7', '1-314': '8', '1-315': '9', '1-405': '10', '1-406': '11', '1-407': '12', '1-408': '13', '1-409': '14', '1-410': '15', '1-411': '16', '1-412': '17', '1-413': '18', '1-414': '19', '1-415': '20', '1-416': '21', '1-417': '22', '1-418': '23', '1-419': '24', '1-420': '25', '1-506': '26', '1-507': '27', '1-508': '28', '1-509': '29', '1-510': '30', '1-511': '31', '1-512': '32', '1-513': '33', '1-514': '34', '1-515': '35', '1-516': '36', '1-517': '37', '1-518': '38', '1-519': '39', '1-520': '40', '1-602': '41', '1-603': '42', '1-604': '43', '1-605': '44', '1-606': '45', '1-607': '46', '1-608': '47', '1-609': '48', '1-610': '49', '1-611': '50', '1-612': '51', '1-613': '52', '1-614': '53', '1-615': '54', '1-616': '55', '1-617': '56', '1-618': '57', '1-619': '58', '1-703': '59', '1-704': '60', '1-705': '61', '1-706': '62', '1-707': '63', '1-708': '64', '1-709': '65', '1-710': '66', '1-711': '67', '1-713': '68', '1-714': '69', '1-715': '70', '1-716': '71', '1-717': '72', '1-718': '73', '1-719': '74', '1-720': '75', '1-721': '76', '1-722': '77', '2-101': '78', '2-102': '79', '2-103': '80', '2-104': '81', '2-201': '82', '2-202': '83', '2-203': '84', '2-204': '85','2-301': '86', '2-302': '87', '2-303': '88', '2-304': '89', '2-305': '90', '2-306': '91', '2-401': '92', '2-402': '93', '2-403': '94', '2-404': '95', '2-501': '96', '2-502': '97', '2-503': '98', '2-504': '99', '2-601': '100', '2-602': '101', '2-603': '102', '2-604': '103', '2-701': '104', '2-702': '105', '2-703': '106', '2-704': '107'}
#获取单间教室名称以及id,并录课
id_=0
for i in range(SL):
A =MC[i]
C=str(A).strip("['")
C=C.strip("']")#教室名称
self.id.append(js_id[C])#教室名称对应id

for i in QD: # 获取每间教室借用信息
for a in range(1, 7): # 检查教室哪节有借用,有则录入
if i[a] == 0:
# print(f"第{a}大节没有借用")
pass
elif i[a] == 1:
ks, js = self.hs(a) # 获取开始结束小节
#print(f"{i[0]}第{ks,js}小节有借用", self.id[id_])
print(self.id[id_],i[0],zc,xq,ks,js)#教室id,教室名称,周次,星期,开始节次,结束节次
self.lk(self.id[id_],i[0],zc,xq,ks,js)

id_ = id_ + 1
sleep(0.1)

向录课平台发送录课数据进行录课的方法

该方法传入教室id,教室名称,周次,星期,开始节次,结束节次,即可向录课平台发送录课请求

注意:该方法是该软件的核心,请注意每个学期对数据进行更新,导致该方法无法使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def lk(self,id,name,zc,xq,ks,js):
data ={
'room_id': id,#教室id 1需要
'room_name':name,#教室名称 1需要
'year': '2024',#年
'term': '1',#学期
'term_start': '2024-09-02',#学期开头日期
'week_no': zc,#周 需要
'weekday': xq,#星期 需要
'section': ks,#从哪小节进入录课界面 1需要
'start_section': ks,#录课的开始节 1需要
'end_section': js,#录课的结束节 2需要
'people_id': '0001130071',#老师id
'audience': '借用',#两个填的地方
'reason': '借用'
}
url = "录课平台URL,防止泄露,故不展示,505电脑中有此记载"
A =requests.post(url,data=data,headers={"cookie":f"{self.cookie2}"})
if "state" in A.text:
print("入录成功")

~

~

~

软件入口main函数py文件

头文件

1
2
3
4
5
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QMessageBox
from PyQt5 import uic
from PyQt5.QtGui import QIcon
import zdlkym

程序入口类

构造函数及其静态变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class zdlk (QWidget):

def __init__(self):
super().__init__()

#实例一个自动录课的登录对象
self.DL = zdlkym.dl()

#定义登录UI和主界面UI
self.dl_ui =None
self.zjm_ui = None
#声明两个获取ui界面的函数
self.init_dl_ui()
self.init_zjm_ui()

#定义cookie
self.jw_cookie=""
self.luke_cookie=""

#定义要用到的数据
# 借用清单,借用数量,借用教室名称,html
self.QD = []
self.SL = 0
self.MC = []
self.html =""

#保存的模版的数据
self.QD_BC = []
self.SL_BC = 0
self.MC_BC = []
self.html_BC = ""

#用户选择的周次和星期和日期
self.zc ="1"
self.xq ="1"
self.zc_BC = "1"
self.xq_BC = "1"
self.rq =""
self.rq_BC=""
#self.luke =自动录课系统.luke(self.zc,self.xq,1,2,1,2,1)

获取登录ui的方法

绑定界面的各种控件的信号和槽函数

1
2
3
4
5
6
#获取登录ui
def init_dl_ui(self):
self.dl_ui= uic.loadUi("./dl.ui")
#判断登录
self.dl_ui.dl_bth.clicked.connect(self.plpd)
#self.dl_ui.dl_bth.clicked.connect(self.xs_zjm)测试

获取主界面ui的方法

绑定界面的各种控件的信号和槽函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 获取主界面ui
def init_zjm_ui(self):
self.zjm_ui = uic.loadUi("./zjm.ui")

#绑定信号和槽
#菜单页面
#查询按钮
self.zjm_ui.bth_cx.clicked.connect(self.cd1)
# 录入按钮
self.zjm_ui.bth_lr.clicked.connect(self.cd2)
# 退出按钮
self.zjm_ui.bth_tc.clicked.connect(self.cd3)

#查询页面
#查询按钮
self.zjm_ui.bth_cx_cx.clicked.connect(self.cx_cx)
#保存按钮
self.zjm_ui.bth_cx_bc.clicked.connect(self.cx_bc)

#录入页面
#查看模板按钮
self.zjm_ui.pushButton_3.clicked.connect(self.lr_ckmb)
#录入按钮
self.zjm_ui.pushButton_4.clicked.connect(self.lr_lr)

测试显示主界面的槽函数,可不用登录进入主界面,测试的时候可用

1
2
3
#测试显示主界面的方法
def xs_zjm(self):
self.zjm_ui.show()

查询页面的查询方法

1
2
3
4
5
6
7
8
9
10
11
12
#查询页面的查询方法
def cx_cx(self):
#获取选择的周次和星期
self.zc = self.zjm_ui.comboBox_zc.currentText()
self.xq = self.zjm_ui.comboBox_xq.currentText()
self.zc, self.xq, jc1, jc2, self.rq =self.DL.sj_hq(self.zc,self.xq)
# 实例一个自动录课系统类的对象
luke = zdlkym.luke(self.zc, self.xq, jc1, jc2,self.rq, self.jw_cookie, self.luke_cookie)
A = luke.cx() # 获取查询到的html
self.QD, self.SL, self.MC = luke.qd(A) # 返回借用清单,借用数量,借用教室名称
self.zjm_ui.textBrowser.setHtml(A.text)
self.html =A.text

保存按钮保存相关数据的槽函数

1
2
3
4
5
6
7
8
9
#保存按钮保存相关数据
def cx_bc(self):
self.QD_BC = self.QD
self.SL_BC = self.SL
self.MC_BC = self.MC
self.html_BC = self.html
self.zc_BC = self.zc
self.xq_BC = self.xq
self.rq_BC =self.rq

登录判断槽函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#登录判断方法
def plpd(self):
# 获取两个用户输入的登录cookie
jw_cookie=self.dl_ui.jw_cookie.text()
luke_cookie=self.dl_ui.luke_cookie.text()

#调用实例的自动录课的登录对象的登录判断函数进行判断
jw_cookie,luke_cookie=self.DL.cdym__ff(jw_cookie,luke_cookie)
if jw_cookie==1:
QMessageBox.warning(self,'登录失败','请检查录课秘钥')
elif jw_cookie==2:
QMessageBox.warning(self, '登录失败', '请检查教务网秘钥')
elif jw_cookie==3:
QMessageBox.warning(self, '登录失败', '您登录后过长时间没有操作或您的用户名已经在别处登录,请重新获取cookie')
else:
#print(123456)——测试是否登录成功使用
#登录成功保存两个cookie
self.jw_cookie =jw_cookie
self.luke_cookie =luke_cookie
self.dl_ui.hide()#隐藏登录界面
self.zjm_ui.show()#显示主界面

主界面三个按钮的槽函数

1
2
3
4
5
6
7
#主界面三个按钮的方法
def cd1(self):
self.zjm_ui.tabWidget_2.setCurrentIndex(0)#切换0查询页面
def cd2(self):
self.zjm_ui.tabWidget_2.setCurrentIndex(1)#切换1录入页面
def cd3(self):
QApplication.quit()#关闭程序

查看模版的按钮的槽函数

1
2
3
4
5
#查看模版的按钮方法
def lr_ckmb(self):
#显示模版信息
a = self.lr_scxx()
self.zjm_ui.textBrowser_2.setText(a)

在模板中输出信息的槽函数(会被上面的查看模版的按钮的槽函数调用)

1
2
3
4
5
6
7
8
9
# 在模板中输出信息的函数
def lr_scxx(self):
a=f"第{self.zc}周,星期{self.xq},借用教室{self.SL_BC}间\n借用教室:\n"
for i in self.MC_BC:
a =a+f"{i}\n"
a =a+"借用清单:\n"
for i in self.QD_BC:
a=a+f"{i}\n"
return a

录入按钮的槽函数

因为教务网每一周的开始时间是星期天,结束为星期六(如在教务网中第一周的星期天为8月31,星期一为9月1),所以如果是星期天的话,就会让周次-1来匹配我们正常的星期

1
2
3
4
5
6
7
#录入函数
def lr_lr(self):
if self.xq_BC =="7":
self.zc_BC=f"{int(self.zc_BC)-1}"
luke = zdlkym.luke(self.zc_BC, self.xq_BC, "1", "11",self.rq_BC, self.jw_cookie, self.luke_cookie)
luke.luk(self.QD_BC,self.SL_BC,self.MC_BC,self.zc_BC,self.xq_BC)
self.zjm_ui.textBrowser_3.setText(f"教室管理平台第{self.zc_BC}周的星期{self.xq_BC}录入成功")

程序入口的启动项方法

1
2
3
4
5
6
7
8
9
10
11
12
13
if __name__ == "__main__":
app = QApplication(sys.argv)
# sys.argv是本程序的运行的一些参数
# 实例一个窗口对象
w = zdlk()
# 展示登录窗口
w.dl_ui.show()
w.setWindowIcon(QIcon('favicon.ico'))
# 设置窗口标题
w.setWindowTitle("自动录课平台")
# 程序进行循环等待状态
# 不停刷新,监测用户操作
app.exec_()

软件界面展示