├── .gitignore
├── README.md
├── UCAS_course.py
├── UCAS_course_bachelor_1.7.py
├── UCAS_course_grad_1.8.py
└── dist
└── UCAS_course.exe
/.gitignore:
--------------------------------------------------------------------------------
1 | *.jpg
2 | *.bat
3 | *.ico
4 | *.spec
5 |
6 | build
7 | dist/*.jpg
8 | __pycache__
9 | .cph
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # UCAS_course_script
2 | A script to enroll in courses for graduate students of University of Chinese Academy of Sciences.
3 |
--------------------------------------------------------------------------------
/UCAS_course.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import tkinter.messagebox
3 | import tkinter
4 | import threading
5 | import time
6 | from PIL import Image, ImageTk
7 | import re
8 |
9 |
10 | # 封装用于 post 的函数,失败返回 None
11 | def post_data(url, data = None, params = None, time_out = 3, retry = 5):
12 | for _ in range(retry):
13 | try:
14 | page = sess.post(url, data = data, params = params, timeout=time_out)
15 | return page
16 | except:
17 | pass
18 | return None
19 |
20 | def update_link():
21 | global Avatar, link_select_course, link_save_course, link_course_manage
22 | if Avatar == '本科生':
23 | link_select_course = 'http://jwxk.ucas.ac.cn/courseManageBachelor/selectCourse'
24 | link_save_course = 'http://jwxk.ucas.ac.cn/courseManageBachelor/saveCourse'
25 | link_course_manage = 'http://jwxk.ucas.ac.cn/courseManageBachelor/main'
26 | else:
27 | link_select_course = 'http://jwxk.ucas.ac.cn/courseManage/selectCourse'
28 | link_save_course = 'http://jwxk.ucas.ac.cn/courseManage/saveCourse'
29 | link_course_manage = 'http://jwxk.ucas.ac.cn/courseManage/main'
30 |
31 |
32 | def login_jwxt(add_id_to_name = 0):
33 | page_jump = post_data('http://sep.ucas.ac.cn/portal/site/226/821')
34 | if page_jump is None:
35 | tkinter.messagebox.showerror(title = '网页超时', message = '请检查是否断网或者延迟过高')
36 | return "high delay"
37 |
38 | pattern_jwxt_id = re.compile('Identity=([\w-]*)') # 匹配数字、字母、下划线和-
39 | try:
40 | iden = re.search(pattern_jwxt_id, page_jump.text).group(1)
41 | except:
42 | tkinter.messagebox.showerror(title = '未预料的错误', message = '没有成功匹配到Identity,请及时联系维护人员')
43 | login_info['text'] = '登录失败了\t\tT_T'
44 | # print(page.text)
45 | return
46 |
47 | jump_payload = {'Identity': iden}
48 | page_jwxt = post_data('http://jwxk.ucas.ac.cn/login', data=jump_payload)
49 | if page_jwxt is None:
50 | tkinter.messagebox.showerror(title = '网页超时', message = '请检查是否断网或者延迟过高')
51 | return "high delay"
52 |
53 | pattern_student_id = re.compile('doSelectNo\?num=([\w]*)')
54 | try:
55 | list_id = re.findall(pattern_student_id, page_jwxt.text)
56 | list_id.sort()
57 | N_id =len(list_id)
58 | student_id = list_id[N_id-1]
59 |
60 | for x in list_id:
61 | print(x)
62 |
63 | student_number_payload = {'num': student_id}
64 | page_check = post_data('http://jwxk.ucas.ac.cn/doSelectNo', data = student_number_payload)
65 | if page_check is None:
66 | tkinter.messagebox.showerror(title = '网页超时', message = '请检查是否断网或者延迟过高')
67 | return "high delay"
68 |
69 | pattern_check = re.compile(' (.+?) \s*\(当前\)')
70 | id_check = re.search(pattern_check, page_check.text).group(1)
71 | if id_check != student_id:
72 | tkinter.messagebox.showerror(title = '内部错误', message = '选择学号失败,请及时联系维护人员')
73 | return "select student id fail"
74 | if add_id_to_name == 1:
75 | global name_student
76 | name_student = name_student + ' ' + student_id
77 | page_jwxt = page_check
78 |
79 | except:
80 | pass
81 |
82 |
83 | global Avatar
84 | list_bks = re.findall(re.compile('(bks)'), page_jwxt.text)
85 | print(list_bks)
86 | if len(list_bks) >0:
87 | Avatar = '本科生'
88 | else:
89 | Avatar = '研究生'
90 |
91 | #print(Avatar)
92 | update_link()
93 | global link_course_manage
94 | page_course_manage = post_data(link_course_manage)
95 | if page_course_manage is None:
96 | tkinter.messagebox.showerror(title = '网页超时', message = '请检查是否断网或者延迟过高')
97 | return "high delay"
98 |
99 | # 以下认为登录已经成功
100 |
101 | pattern_select_course_s = re.compile('\?s=(.*?)";')
102 | select_course_s = re.search(pattern_select_course_s, page_course_manage.text).group(1)
103 |
104 | pattern_deptIds = re.compile('label for="id_(\d+)"')
105 | deptIds = re.findall(pattern_deptIds, page_course_manage.text)
106 |
107 | global select_course_payload
108 | #select_course_payload = {'deptIds': deptIds}
109 | global query_s
110 | query_s = select_course_s
111 | select_course_payload = {'s': select_course_s, 'deptIds': deptIds}
112 |
113 | return 'ok'
114 |
115 | def login(event = None):
116 | user = user_input.get()
117 | pwd = pwd_input.get()
118 | code = cert_code_input.get()
119 | login_payload = {'userName': user, 'pwd': pwd, 'certCode': code, 'sb': 'sb'}
120 |
121 | global login_info, root
122 | login_info['text'] = '登录SEP...\t\t=_ = '
123 | root.update_idletasks()
124 |
125 | # 尝试连接sep来登录
126 | page_after_login = post_data('http://sep.ucas.ac.cn/slogin', data = login_payload)
127 | if page_after_login is None:
128 | tkinter.messagebox.showerror(title = '网页超时', message = '请检查是否断网或者延迟过高')
129 | login_info['text'] = '登录失败了\t\tT_T'
130 | return
131 | # 判断是否仍停留在选课界面
132 |
133 | pattern_login_error = re.compile('
(.+?)
', re.S)
134 | try:
135 | err_type = re.search(pattern_login_error, page_after_login.text).group(1)
136 | tkinter.messagebox.showerror(title = '信息有误', message = err_type)
137 | if err_type == '密码错误':
138 | pwd_input.delete(0, tkinter.END)
139 | elif err_type == '验证码错误':
140 | cert_code_input.delete(0, tkinter.END)
141 | login_info['text'] = '登录失败了\t\tT_T'
142 | return
143 | except:
144 | pass # 信息没有错误
145 |
146 | # 尝试用正则表达式匹配姓名来判断是否成功进入sep主页面
147 | pattern_name = re.compile('"当前用户所在单位"> (.+?) (.+?)', re.S)
148 | try:
149 | global name_student
150 | name_student = re.search(pattern_name, page_after_login.text).group(2)
151 | # print(name)
152 | except:
153 | tkinter.messagebox.showerror(title = '未能成功进入 SEP', message = '请仔细检查输入的用户名、密码以及验证码')
154 | login_info['text'] = '登录失败了\t\tT_T'
155 | return
156 |
157 | login_info['text'] = '登录选课系统...\t\t>_<'
158 | root.update_idletasks()
159 |
160 | res = login_jwxt(add_id_to_name = 1)
161 |
162 | if res != 'ok':
163 | login_info['text'] = '登录失败了\t\tT_T'
164 | return
165 | login_info['text'] = '欢迎 ' + name_student + ' ^_^'
166 |
167 | # 锁住登录信息(目前来看作用只是以防万一)
168 | #select_bachlor['state'] = tkinter.DISABLED
169 | #select_graduate['state'] = tkinter.DISABLED
170 |
171 | def relogin():
172 | page_jump = post_data('http://sep.ucas.ac.cn/appStore')
173 | if page_jump is None:
174 | tkinter.messagebox.showerror(title = '请重新登录', message = '请检查是否断网或者延迟过高')
175 | return "high delay"
176 |
177 | pattern_offline = re.compile('SEP 教育业务接入平台')
178 | if re.search(pattern_offline, page_jump.text) != None:
179 | tkinter.messagebox.showerror(title = '请重新登录', message = '看起来已经好久没有操作了')
180 | return "sign out"
181 |
182 | res = login_jwxt()
183 | return res
184 |
185 | def check_before_select():
186 | log['text'] = ''
187 |
188 | global select_course_payload, Avatar
189 |
190 | if Avatar is None:
191 | tkinter.messagebox.showerror(title = '错误', message = '您还未登录')
192 | global auto_working # 标记是否在捡漏,0 表示不在捡漏,1 表示在捡漏
193 | auto_working = 0
194 | jianlou_switch['text'] = '捡漏'
195 | return None
196 |
197 | global link_select_course
198 | page_select_course = post_data(link_select_course, select_course_payload)
199 | if page_select_course is None:
200 | select_result['text'] = '网页超时 没有进行选课'
201 | return None
202 |
203 | off_line = re.search('你的会话已失效或身份已改变,请重新登录', page_select_course.text)
204 | if off_line: # 至少已经从选课系统中掉线
205 | global login_info, root
206 | login_info['text'] = '掉线了,自动重连中...\t=_ = '
207 | root.update_idletasks()
208 |
209 | res = relogin()
210 | if res != 'ok': # 甚至从SEP系统中掉线
211 | init()
212 | select_result['text'] = '您已经掉线'
213 | login_info['text'] = '您已经掉线'
214 | return None
215 | else:
216 | login_info['text'] = '欢迎 ' + name_student + '\t^_^'
217 | root.update_idletasks()
218 |
219 | page_select_course = post_data(link_select_course, select_course_payload)
220 | if page_select_course is None:
221 | select_result['text'] = '网页超时 没有进行选课'
222 | return None
223 |
224 | system_closed = re.search('为了给您提供更好的服务', page_select_course.text)
225 | if system_closed:
226 | select_result['text'] = '选课系统未开放'
227 | return None
228 |
229 | select_result['text'] = '正在选课'
230 | return page_select_course
231 |
232 | def generate_log(select_result_page):
233 | pattern = re.compile('class="success">(.+?)')
234 | success_message = re.search(pattern, select_result_page.text)
235 | pattern = re.compile('class="error">(.+?)')
236 | error_message = re.search(pattern, select_result_page.text)
237 | success = 0
238 | if success_message is not None:
239 | messages = success_message.group(1).split('
')
240 | success = 1
241 | elif error_message is not None:
242 | messages = error_message.group(1).split('
')
243 | else:
244 | messages = ['403 Forbidden']
245 |
246 | for single_message in messages:
247 | message_str = single_message
248 | if len(message_str) == 0:
249 | continue
250 | if len(message_str) > 25:
251 | message_str = message_str[:25] + '\n' + message_str[25:]
252 | if success:
253 | log_success['text'] += message_str + '\n' + sep_time['text'] + '\n'
254 | log['text'] += message_str + '\n' + sep_time['text'] + '\n'
255 |
256 | def add_course_code_to_payload(course, select_course_page):
257 | pattern = re.compile('id="courseCode_(.*?)">%s' % course)
258 | course_code = re.search(pattern, select_course_page.text)
259 | if course_code is None:
260 | log['text'] += course + ': 该课程编码不可用(可能已经选过了)' + '\n' + sep_time['text'] + '\n'
261 | return 0
262 | else:
263 | select_course_payload['sids'].append(course_code.group(1))
264 | return 1
265 |
266 | def list_split(list):
267 | list = re.split('[,,]',list)
268 | res = []
269 | for x in list:
270 | x = x.strip()
271 | if x != '':
272 | res.append(x)
273 | return res
274 |
275 | def get_csrftoken(select_course_page):
276 | global select_course_payload
277 | pattern_get_csrftoken = re.compile('name="_csrftoken" value="(.*?)"')
278 | value = re.search(pattern_get_csrftoken, select_course_page.text).group(1)
279 | select_course_payload['_csrftoken'] = value
280 |
281 |
282 | def select_separately(event):
283 | select_course_page = check_before_select()
284 | if select_course_page is None:
285 | return
286 |
287 | course_list = list_split(course_input_separate.get())
288 |
289 | global Avatar, link_save_course, link_select_course
290 |
291 | sess.headers.update({"Referer": link_select_course + "?s=" + query_s})
292 | for course in course_list:
293 | select_course_page = check_before_select()
294 | select_course_payload['sids'] = []
295 | if add_course_code_to_payload(course, select_course_page) == 0:
296 | continue
297 |
298 | get_csrftoken(select_course_page)
299 | select_result_page = post_data(link_save_course, select_course_payload)
300 | if select_result_page is None:
301 | log['text'] += course + ': 网页超时'+' \n ' + sep_time['text'] + '\n'
302 | else:
303 | generate_log(select_result_page)
304 | del select_course_payload['_csrftoken']
305 |
306 | del sess.headers['Referer']
307 | select_result['text'] = '选课完成'
308 |
309 | def select_together(event):
310 | select_course_page = check_before_select()
311 | if select_course_page is None:
312 | return
313 |
314 | course_list = list_split(course_input.get())
315 |
316 | select_course_payload['sids'] = []
317 | for course in course_list:
318 | add_course_code_to_payload(course, select_course_page)
319 |
320 | if len(select_course_payload['sids']) == 0:
321 | select_result['text'] = '课程代码均不可用'
322 | return
323 |
324 | global Avatar, link_save_course, link_select_course, link_course_manage
325 |
326 | get_csrftoken(select_course_page)
327 | sess.headers.update({"Referer": link_select_course + "?s=" + query_s})
328 |
329 | select_result_page = post_data(link_save_course + "?s=" + query_s, data = select_course_payload)
330 |
331 | del select_course_payload['_csrftoken']
332 | del sess.headers['Referer']
333 |
334 | #print(result_page.text)
335 | if select_result_page is None:
336 | select_result['text'] = '网页超时 没有进行选课'
337 | else:
338 | generate_log(select_result_page)
339 | select_result['text'] = '选课完成'
340 |
341 |
342 | def get_time():
343 | while True:
344 | try:
345 | current_time = requests.get('http://jwxk.ucas.ac.cn/courseManage/main', timeout=3)
346 | current_time = current_time.headers
347 | current_time = current_time['Date']
348 | hour = current_time[17:19]
349 | minute = current_time[20:22]
350 | second = current_time[23:25]
351 | hour = (int(hour) + 8) % 24
352 | time_str = str(hour) + ':' + minute + ':' + second
353 | sep_time['text'] = time_str
354 | time.sleep(1)
355 | root.update_idletasks()
356 | except:
357 | pass
358 |
359 | def auto_select():
360 | global auto_working
361 | global login_mark
362 |
363 | while True:
364 | if auto_working:
365 | select_separately(None)
366 | time.sleep(1)
367 |
368 |
369 | def auto_switch(event):
370 | global auto_working
371 |
372 | if auto_working == 0:
373 | tkinter.messagebox.showinfo(title = '提示',
374 | message = '1.请先使用“分开选”功能,确认提示信息为“超过限选人数”(而无其他错误)后再使用此功能\n'
375 | '2.此模式每1s自动进行一次“分开选”(温馨提示:持续过长有风险)\n'
376 | '3.如若中途掉线,需要自己手动重新登录')
377 | jianlou_switch['text'] = '停止'
378 | else:
379 | jianlou_switch['text'] = '捡漏'
380 | auto_working = 1 - auto_working
381 |
382 |
383 | def download_image_file(event):
384 | global sess, login_info
385 |
386 | login_info['text'] = ''
387 | try:
388 | html = sess.get('http://sep.ucas.ac.cn/randomcode.jpg', timeout = 3)
389 | except:
390 | login_info['text'] = '网页超时 请重新获取验证码'
391 | return
392 |
393 | fp = open("certcode.jpg", 'wb')
394 | fp.write(html.content)
395 | fp.close()
396 |
397 | global cert_photo, show_pic
398 | cert_img = Image.open("certcode.jpg")
399 | cert_img = cert_img.resize((100, 25), Image.ANTIALIAS) # 调整大小 Image.ANTIALIAS 抗锯齿
400 | cert_photo = ImageTk.PhotoImage(cert_img)
401 | show_pic['image'] = cert_photo
402 |
403 | cert_code_input.delete(0, tkinter.END)
404 |
405 | # 初始化
406 | def init():
407 | # 全局变量
408 | global select_course_payload # 用于选课的 payload,记录用于选课的 cid 和 要选的课程编号
409 | select_course_payload = None
410 |
411 | global auto_working # 标记是否在捡漏,0 表示不在捡漏,1 表示在捡漏
412 | auto_working = 0
413 | jianlou_switch['text'] = '捡漏'
414 |
415 | global sess # 全局session
416 | sess = requests.session()
417 | sess.headers.update({'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 Edg/92.0.902.84'}) # 给 seesion 做伪装,通过浏览器检测
418 |
419 | global Avatar # 标明用本科生/研究生身份登录
420 | Avatar = None
421 |
422 | download_image_file(None)
423 |
424 | #select_bachlor['state'] = tkinter.NORMAL
425 | #select_graduate['state'] = tkinter.NORMAL
426 |
427 |
428 | def sign_out():
429 | global Avatar
430 | if Avatar == None:
431 | tkinter.messagebox.showerror(title = 'Error', message = '您尚未登录')
432 | return
433 | init()
434 | login_info['text'] = '成功下线'
435 |
436 | if __name__ == "__main__":
437 | global root
438 | root = tkinter.Tk()
439 | root.title("UCAS_course")
440 | root.geometry('615x580')
441 | root.resizable(width = False, height = False)
442 |
443 | menubar = tkinter.Menu(root)
444 | menubar.add_command(label = "下线", command = sign_out)
445 | root.config(menu = menubar)
446 |
447 | sep_time = tkinter.Label(root, font = ('Calibri', '10'))
448 | sep_time.grid(row = 0, column = 1, sticky = tkinter.E) #紧贴右侧
449 |
450 | thread_time = threading.Thread(target = get_time)
451 | thread_time.setDaemon(True)
452 | thread_time.start()
453 |
454 | global login_info
455 | login_info = tkinter.Label(root, text = '')
456 | login_info.grid(row = 6, column = 0, sticky = tkinter.W) #紧贴左侧
457 | login_info['font'] = ('Calibri', '14')
458 |
459 | tkinter.Label(root, text = '用户名(同sep)', font = ('Calibri', '14')).grid(row = 0, column = 0, sticky = tkinter.W)
460 | user_input = tkinter.Entry(root)
461 | user_input.grid(row = 1, column = 0, sticky = tkinter.W)
462 | user_input['font'] = ('Calibri', '14')
463 | user_input['width'] = 30
464 |
465 | tkinter.Label(root, text = '密码', font=('Calibri', '14')).grid(row = 0, column = 1, sticky = tkinter.W)
466 | pwd_input = tkinter.Entry(root)
467 | pwd_input['show'] = '*'
468 | pwd_input['width'] = 30
469 | pwd_input.grid(row = 1, column = 1, sticky = tkinter.W)
470 | pwd_input['font'] = ('Calibri', '14')
471 | pwd_input.bind('', login)
472 |
473 | # 验证码 Frame
474 | frame_cert = tkinter.Frame(master = root, bd = 0, relief = tkinter.RAISED, width = 1)
475 | frame_cert.grid(row = 2, column = 0, sticky = tkinter.W)
476 | # text
477 | tkinter.Label(master = frame_cert, text = '验证码', font = ('Calibri', '14')).pack(side = tkinter.LEFT, padx = 0)
478 | # input entry
479 | global cert_code_input
480 | cert_code_input = tkinter.Entry(master = frame_cert)
481 | cert_code_input['width'] = 5
482 | cert_code_input.pack(side = tkinter.LEFT, padx = 4)
483 | cert_code_input['font'] = ('Calibri', '14')
484 | cert_code_input.bind('', login)
485 | # picture
486 | global show_pic
487 | show_pic = tkinter.Label(master = frame_cert)
488 | show_pic.pack(side = tkinter.LEFT, padx = 4)
489 | # buttom
490 | get_pic = tkinter.Button(master = frame_cert, text = '刷新')
491 | get_pic.pack(side = tkinter.LEFT, padx = 4)
492 | get_pic['width'] = 5
493 | get_pic['font'] = ('Calibri', '14')
494 | get_pic.bind('', download_image_file)
495 | get_pic.bind('', download_image_file)
496 |
497 | # 选择身份
498 | '''
499 | global avatar_input
500 | avatar_input = tkinter.StringVar() # 定义变量记录所选身份
501 | avatar_input.set('本科生')
502 | frame_avatar = tkinter.Frame(master = root, bd = 0, relief = tkinter.RAISED, width = 1)
503 | frame_avatar.grid(row = 2, column = 1, sticky = tkinter.W)
504 | select_bachlor = tkinter.Radiobutton(frame_avatar, text = '本科生', variable = avatar_input, value = '本科生') # 默认设置本科生
505 | select_bachlor.pack(side = tkinter.LEFT, padx = 4)
506 | select_bachlor.bind('', login)
507 | select_graduate = tkinter.Radiobutton(frame_avatar, text = '研究生', variable = avatar_input, value = '研究生')
508 | select_graduate.pack(side = tkinter.LEFT, padx = 4)
509 | select_graduate.bind('', login)
510 | #print(avatar_input.get())
511 | '''
512 |
513 | login_button = tkinter.Button(root, text = '登 录')
514 | login_button['width'] = 6
515 | login_button['font'] = ('Calibri', '14')
516 | login_button.grid(row = 6, column = 1, sticky = tkinter.E)
517 | login_button.bind('', login)
518 | login_button.bind('', login)
519 |
520 | select_result = tkinter.Label(root, text = '')
521 | select_result.grid(row = 9, sticky = tkinter.W)
522 | select_result['font'] = ('Calibri', '14')
523 |
524 | tkinter.Label(root, text = '课程编码(一起选) 用逗号分隔', font = ('Calibri', '14')).grid(row = 7, column = 0, sticky = tkinter.W)
525 | course_input = tkinter.Entry(root)
526 | course_input['width'] = 30
527 | course_input.grid(row = 8, column = 0, sticky = tkinter.W)
528 | course_input['font'] = ('Calibri', '14')
529 | course_input.bind('', select_together)
530 |
531 | tkinter.Label(root, text = '课程编码(分开选) 用逗号分隔', font=('Calibri', '14')).grid(row = 7, column = 1, sticky = tkinter.W)
532 | course_input_separate = tkinter.Entry(root)
533 | course_input_separate['width'] = 30
534 | course_input_separate.grid(row = 8, column = 1, sticky = tkinter.W)
535 | course_input_separate['font'] = ('Calibri', '14')
536 | course_input_separate.bind('', select_separately)
537 |
538 | course_choose = tkinter.Button(root, text = '一起选')
539 | course_choose.bind('', select_together)
540 | course_choose['font'] = ('Calibri', '14')
541 | course_choose['width'] = 6
542 | course_choose.grid(row = 9, column = 0, sticky = tkinter.E)
543 |
544 | course_choose = tkinter.Button(root, text = '分开选')
545 | course_choose.bind('', select_separately)
546 | course_choose['font'] = ('Calibri', '14')
547 | course_choose['width'] = 6
548 | course_choose.grid(row = 9, column = 1, sticky = tkinter.E)
549 |
550 | jianlou_switch = tkinter.Button(root, text = '捡 漏')
551 | jianlou_switch.bind('', auto_switch)
552 | jianlou_switch['font'] = ('Calibri', '14')
553 | jianlou_switch['width'] = 6
554 | jianlou_switch.grid(row = 9, column = 1, sticky = tkinter.W)
555 |
556 | tkinter.Label(root, text = 'Log:', font=('Calibri', '14')).grid(row = 11, column = 0, sticky = tkinter.W)
557 | log = tkinter.Label(root, anchor = 'nw', justify = 'left', background = 'white', relief = 'sunken', height = 21, width = 50,
558 | borderwidth = 2)
559 | log.grid(row = 12, column = 0, sticky = tkinter.W)
560 | log['font'] = ('Calibri', '9')
561 |
562 | tkinter.Label(root, text = 'Log_Success:', font=('Calibri', '14')).grid(row = 11, column = 1, sticky = tkinter.W)
563 | log_success = tkinter.Label(root, anchor = 'nw', justify = 'left', background = 'white', relief = 'sunken', height = 21,
564 | width = 50, borderwidth = 2)
565 | log_success.grid(row = 12, column = 1, sticky = tkinter.W)
566 | log_success['font'] = ('Calibri', '9')
567 |
568 | init()
569 | thread_auto_select = threading.Thread(target = auto_select)
570 | thread_auto_select.setDaemon(True)
571 | thread_auto_select.start()
572 | root.mainloop()
573 |
--------------------------------------------------------------------------------
/UCAS_course_bachelor_1.7.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import tkinter.messagebox
3 | import tkinter
4 | import threading
5 | import time
6 | from PIL import Image, ImageTk
7 | import re
8 |
9 |
10 | def post_data(url, data=None, time_out=3, retry=5):
11 | for _ in range(retry):
12 | try:
13 | page = sess.post(url, data=data, timeout=time_out)
14 | return page
15 | except:
16 | pass
17 | return None
18 |
19 |
20 | def check_online():
21 | log['text'] = ''
22 |
23 | if select_course_payload is None:
24 | tkinter.messagebox.showerror(title='错误', message='您还未登录')
25 | return None
26 |
27 | page = post_data('http://jwxk.ucas.ac.cn/courseManageBachelor/selectCourse', select_course_payload)
28 | if page is None:
29 | select_result['text'] = '网页超时 没有进行选课'
30 | return None
31 |
32 | off_line = re.search('你的会话已失效或身份已改变,请重新登录', page.text)
33 | if off_line:
34 | select_result['text'] = '您已经掉线'
35 | login_info['text'] = '您已经掉线'
36 | return None
37 |
38 | system_closed = re.search('为了给您提供更好的服务', page.text)
39 | if system_closed:
40 | select_result['text'] = '选课系统未开放'
41 | return None
42 |
43 | select_result['text'] = '正在选课'
44 | return page
45 |
46 |
47 | def generate_log(select_result_page):
48 | pattern = re.compile('class="success">(.+?)')
49 | success_message = re.search(pattern, select_result_page.text)
50 | pattern = re.compile('class="error">(.+?)')
51 | error_message = re.search(pattern, select_result_page.text)
52 | success = 0
53 | if success_message is not None:
54 | messages = success_message.group(1).split('
')
55 | success = 1
56 | elif error_message is not None:
57 | messages = error_message.group(1).split('
')
58 | else:
59 | messages = ['403 Forbidden']
60 |
61 | for single_message in messages:
62 | message_str = single_message
63 | if len(message_str) == 0:
64 | continue
65 | if len(message_str) > 25:
66 | message_str = message_str[:25] + '\n' + message_str[25:]
67 | if success:
68 | log_success['text'] += message_str + '\n' + sep_time['text'] + '\n'
69 | log['text'] += message_str + '\n' + sep_time['text'] + '\n'
70 |
71 |
72 | def add_course_code_to_payload(course, select_course_page):
73 | pattern = re.compile('id="courseCode_(.*?)">%s' % course)
74 | course_code = re.search(pattern, select_course_page.text)
75 | if course_code is None:
76 | log['text'] += course + ': 该课程编码不可用(可能已经选过了)' + '\n' + sep_time['text'] + '\n'
77 | return 1
78 | else:
79 | select_course_payload['sids'].append(course_code.group(1))
80 | return 0
81 |
82 |
83 | def select_separately(event):
84 | select_course_page = check_online()
85 | if select_course_page is None:
86 | return
87 |
88 | course_list = course_input_separate.get()
89 | course_list = course_list.split()
90 | for course in course_list:
91 | select_course_payload['sids'] = []
92 | if add_course_code_to_payload(course, select_course_page):
93 | continue
94 |
95 | select_result_page = post_data('http://jwxk.ucas.ac.cn/courseManageBachelor/saveCourse', select_course_payload)
96 | if select_result_page is None:
97 | log['text'] += course + ': 网页超时'+' \n ' + sep_time['text'] + '\n'
98 | else:
99 | generate_log(select_result_page)
100 |
101 | select_result['text'] = '选课完成'
102 |
103 |
104 | def select_together(event):
105 | select_course_page = check_online()
106 | if select_course_page is None:
107 | return
108 |
109 | course_list = course_input.get()
110 | course_list = course_list.split()
111 | select_course_payload['sids'] = []
112 | for course in course_list:
113 | add_course_code_to_payload(course, select_course_page)
114 |
115 | if len(select_course_payload['sids']) == 0:
116 | select_result['text'] = '课程代码均不可用'
117 | return
118 |
119 | select_result_page = post_data('http://jwxk.ucas.ac.cn/courseManageBachelor/saveCourse', select_course_payload)
120 | if select_result_page is None:
121 | select_result['text'] = '网页超时 没有进行选课'
122 | else:
123 | generate_log(select_result_page)
124 | select_result['text'] = '选课完成'
125 |
126 |
127 | def login(event):
128 | user = user_input.get()
129 | pwd = pwd_input.get()
130 | code = cert_code_input.get()
131 | login_payload = {'userName': user, 'pwd': pwd, 'certCode': code, 'sb': 'sb'}
132 |
133 | login_info['text'] = '正在登录'
134 | root.update_idletasks()
135 |
136 | page = post_data('http://sep.ucas.ac.cn/slogin', data=login_payload)
137 | if page is None:
138 | login_info['text'] = '网页超时 请重新登录'
139 | return
140 |
141 | pattern = re.compile(' (.+?)', re.S)
142 | try:
143 | name = re.search(pattern, page.text).group(1)
144 | except:
145 | login_info['text'] = '信息有误'
146 | return
147 |
148 | page = post_data('http://sep.ucas.ac.cn/portal/site/226/821')
149 | if page is None:
150 | login_info['text'] = '网页超时 请重新登录'
151 | return
152 |
153 | pattern = re.compile('Identity=([\w-]*)')
154 | try:
155 | iden = re.search(pattern, page.text).group(1)
156 | except:
157 | login_info['text'] = '没有成功匹配到Identity,请及时联系作者'
158 | return
159 |
160 | login_info['text'] = '正在跳转'
161 | root.update_idletasks()
162 |
163 | jump_payload = {'Identity': iden}
164 | page = post_data('http://jwxk.ucas.ac.cn/login', data=jump_payload)
165 | if page is None:
166 | login_info['text'] = '网页超时 请重新登录'
167 | return
168 |
169 | pattern = re.compile('"_id_1"> (.+?)')
170 | try:
171 | student_number = re.search(pattern, page.text).group(1)
172 | student_number_payload = {'num': student_number, 'sb': 'y'}
173 | page = post_data('http://jwxk.ucas.ac.cn/doSelectNo', data=student_number_payload)
174 | if page is None:
175 | login_info['text'] = '网页超时 请重新登录'
176 | return
177 | except:
178 | pass
179 |
180 | page = post_data('http://jwxk.ucas.ac.cn/courseManageBachelor/main')
181 | if page is None:
182 | login_info['text'] = '网页超时 请重新登录'
183 | return
184 | pattern = re.compile('\?s=(.*?)";')
185 | select_course_s = re.search(pattern, page.text).group(1)
186 | pattern = re.compile('label for="id_(\d+)"')
187 | deptIds = re.findall(pattern, page.text)
188 | global select_course_payload
189 | select_course_payload = {'s': select_course_s, 'deptIds': deptIds, 'sb': 'y'}
190 | login_info['text'] = '登陆成功 ' + name
191 |
192 |
193 | def get_time():
194 | while True:
195 | try:
196 | current_time = requests.get('http://jwxk.ucas.ac.cn/courseManageBachelor/main', timeout=3)
197 | current_time = current_time.headers
198 | current_time = current_time['Date']
199 | hour = current_time[17:19]
200 | minute = current_time[20:22]
201 | second = current_time[23:25]
202 | hour = int(hour) + 8
203 | time_str = str(hour) + ':' + minute + ':' + second
204 | sep_time['text'] = time_str
205 | time.sleep(1)
206 | root.update_idletasks()
207 | except:
208 | pass
209 |
210 |
211 | def auto_select():
212 | global auto_working
213 | while True:
214 | if auto_working and login_info['text'] != '您已经掉线':
215 | select_separately(None)
216 | time.sleep(1)
217 |
218 |
219 | def auto_switch(event):
220 | global auto_working
221 | if auto_working == 0:
222 | tkinter.messagebox.showinfo(title='提示',
223 | message='1.请先使用“分开选”功能,确认提示信息为“超过限选人数”(而无其他错误)后再使用此功能\n'
224 | '2.此模式每1s自动进行一次“分开选”\n'
225 | '3.如若中途掉线,需要自己手动重新登录')
226 | jianlou_switch['text'] = '停止'
227 | else:
228 | jianlou_switch['text'] = '捡漏'
229 | auto_working = 1 - auto_working
230 |
231 |
232 | def download_image_file(event):
233 | global sess
234 | sess = requests.session()
235 | login_info['text'] = ''
236 | try:
237 | html = sess.get('http://sep.ucas.ac.cn/changePic', timeout=3)
238 | except:
239 | login_info['text'] = '网页超时 请重新获取验证码'
240 | return
241 |
242 | fp = open("certcode.jpg", 'wb')
243 | fp.write(html.content)
244 | fp.close()
245 | global cert_photo
246 | cert_img = Image.open("certcode.jpg")
247 | cert_photo = ImageTk.PhotoImage(cert_img)
248 | show_pic['image'] = cert_photo
249 |
250 |
251 | if __name__ == "__main__":
252 | auto_working = 0
253 | login_check = 0
254 | root = tkinter.Tk()
255 | root.title("UCAS_course_grad 1.7 by wyf && YaoBIG QQ:751076061")
256 | root.geometry('620x640')
257 | root.resizable(width=False, height=False)
258 |
259 | sep_time = tkinter.Label(root, font=('Calibri', '10'))
260 | sep_time.grid(row=0, column=1, sticky=tkinter.E)
261 |
262 | thread_1 = threading.Thread(target=get_time)
263 | thread_1.setDaemon(True)
264 | thread_1.start()
265 |
266 | thread_2 = threading.Thread(target=auto_select)
267 | thread_2.setDaemon(True)
268 | thread_2.start()
269 |
270 | login_info = tkinter.Label(root, text='')
271 | login_info.grid(row=6, column=0, sticky=tkinter.W)
272 | login_info['font'] = ('Calibri', '14')
273 |
274 | select_result = tkinter.Label(root, text='')
275 | select_result.grid(row=9, sticky=tkinter.W)
276 | select_result['font'] = ('Calibri', '14')
277 |
278 | tkinter.Label(root, text='用户名(同sep)', font=('Calibri', '14')).grid(row=0, column=0, sticky=tkinter.W)
279 | user_input = tkinter.Entry(root)
280 | user_input.grid(row=1, column=0, sticky=tkinter.W)
281 | user_input['font'] = ('Calibri', '14')
282 | user_input['width'] = 30
283 |
284 | tkinter.Label(root, text='密码', font=('Calibri', '14')).grid(row=0, column=1, sticky=tkinter.W)
285 | pwd_input = tkinter.Entry(root)
286 | pwd_input['show'] = '*'
287 | pwd_input['width'] = 30
288 | pwd_input.grid(row=1, column=1, sticky=tkinter.W)
289 | pwd_input['font'] = ('Calibri', '14')
290 | pwd_input.bind('', login)
291 |
292 | get_pic = tkinter.Button(root, text='重新获取验证码')
293 | get_pic['width'] = 12
294 | get_pic.grid(row=5, column=1, sticky=tkinter.W)
295 | get_pic['font'] = ('Calibri', '14')
296 | get_pic.bind('', download_image_file)
297 |
298 | show_pic = tkinter.Label(root)
299 | show_pic.grid(row=5, column=1, sticky=tkinter.E)
300 | download_image_file(None)
301 |
302 | tkinter.Label(root, text='验证码', font=('Calibri', '14')).grid(row=2, column=0, sticky=tkinter.W)
303 |
304 | cert_code_input = tkinter.Entry(root)
305 | cert_code_input['width'] = 30
306 | cert_code_input.grid(row=5, column=0, sticky=tkinter.W)
307 | cert_code_input['font'] = ('Calibri', '14')
308 | cert_code_input.bind('', login)
309 |
310 | login_button = tkinter.Button(root, text='登 录')
311 | login_button['width'] = 6
312 | login_button['font'] = ('Calibri', '14')
313 | login_button.grid(row=6, column=1, sticky=tkinter.E)
314 | login_button.bind('', login)
315 |
316 | tkinter.Label(root, text='课程编码(一起选) 用空格连接', font=('Calibri', '14')).grid(row=7, column=0, sticky=tkinter.W)
317 | course_input = tkinter.Entry(root)
318 | course_input['width'] = 30
319 | course_input.grid(row=8, column=0, sticky=tkinter.W)
320 | course_input['font'] = ('Calibri', '14')
321 | course_input.bind('', select_together)
322 |
323 | tkinter.Label(root, text='课程编码(分开选) 用空格连接', font=('Calibri', '14')).grid(row=7, column=1, sticky=tkinter.W)
324 | course_input_separate = tkinter.Entry(root)
325 | course_input_separate['width'] = 30
326 | course_input_separate.grid(row=8, column=1, sticky=tkinter.W)
327 | course_input_separate['font'] = ('Calibri', '14')
328 | course_input_separate.bind('', select_separately)
329 |
330 | course_choose = tkinter.Button(root, text='一起选')
331 | course_choose.bind('', select_together)
332 | course_choose['font'] = ('Calibri', '14')
333 | course_choose['width'] = 6
334 | course_choose.grid(row=9, column=0, sticky=tkinter.E)
335 |
336 | course_choose = tkinter.Button(root, text='分开选')
337 | course_choose.bind('', select_separately)
338 | course_choose['font'] = ('Calibri', '14')
339 | course_choose['width'] = 6
340 | course_choose.grid(row=9, column=1, sticky=tkinter.E)
341 |
342 | jianlou_switch = tkinter.Button(root, text='捡 漏')
343 | jianlou_switch.bind('', auto_switch)
344 | jianlou_switch['font'] = ('Calibri', '14')
345 | jianlou_switch['width'] = 6
346 | jianlou_switch.grid(row=9, column=1, sticky=tkinter.W)
347 |
348 | tkinter.Label(root, text='Log:', font=('Calibri', '14')).grid(row=11, column=0, sticky=tkinter.W)
349 | log = tkinter.Label(root, anchor='nw', justify='left', background='white', relief='sunken', height=21, width=50,
350 | borderwidth=2)
351 | log.grid(row=12, column=0, sticky=tkinter.W)
352 | log['font'] = ('Calibri', '9')
353 |
354 | tkinter.Label(root, text='Log_Success:', font=('Calibri', '14')).grid(row=11, column=1, sticky=tkinter.W)
355 | log_success = tkinter.Label(root, anchor='nw', justify='left', background='white', relief='sunken', height=21,
356 | width=50, borderwidth=2)
357 | log_success.grid(row=12, column=1, sticky=tkinter.W)
358 | log_success['font'] = ('Calibri', '9')
359 |
360 | root.mainloop()
361 |
362 |
--------------------------------------------------------------------------------
/UCAS_course_grad_1.8.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import tkinter.messagebox
3 | import tkinter
4 | import threading
5 | import time
6 | from PIL import Image, ImageTk
7 | import re
8 |
9 |
10 | def post_data(url, data=None, time_out=3, retry=5):
11 | for _ in range(retry):
12 | try:
13 | page = sess.post(url, data=data, timeout=time_out)
14 | return page
15 | except:
16 | pass
17 | return None
18 |
19 |
20 | def check_online():
21 | log['text'] = ''
22 |
23 | if select_course_payload is None:
24 | tkinter.messagebox.showerror(title='错误', message='您还未登录')
25 | return None
26 |
27 | page = post_data('http://jwxk.ucas.ac.cn/courseManage/selectCourse', select_course_payload)
28 | if page is None:
29 | select_result['text'] = '网页超时 没有进行选课'
30 | return None
31 |
32 | off_line = re.search('你的会话已失效或身份已改变,请重新登录', page.text)
33 | if off_line:
34 | select_result['text'] = '您已经掉线'
35 | login_info['text'] = '您已经掉线'
36 | return None
37 |
38 | system_closed = re.search('为了给您提供更好的服务', page.text)
39 | if system_closed:
40 | select_result['text'] = '选课系统未开放'
41 | return None
42 |
43 | select_result['text'] = '正在选课'
44 | return page
45 |
46 |
47 | def generate_log(select_result_page):
48 | pattern = re.compile('class="success">(.+?)')
49 | success_message = re.search(pattern, select_result_page.text)
50 | pattern = re.compile('class="error">(.+?)')
51 | error_message = re.search(pattern, select_result_page.text)
52 | success = 0
53 | if success_message is not None:
54 | messages = success_message.group(1).split('
')
55 | success = 1
56 | elif error_message is not None:
57 | messages = error_message.group(1).split('
')
58 | else:
59 | messages = ['403 Forbidden']
60 |
61 | for single_message in messages:
62 | message_str = single_message
63 | if len(message_str) == 0:
64 | continue
65 | if len(message_str) > 25:
66 | message_str = message_str[:25] + '\n' + message_str[25:]
67 | if success:
68 | log_success['text'] += message_str + '\n' + sep_time['text'] + '\n'
69 | log['text'] += message_str + '\n' + sep_time['text'] + '\n'
70 |
71 |
72 | def add_course_code_to_payload(course, select_course_page):
73 | pattern = re.compile('id="courseCode_(.*?)">%s' % course)
74 | course_code = re.search(pattern, select_course_page.text)
75 | if course_code is None:
76 | log['text'] += course + ': 该课程编码不可用(可能已经选过了)' + '\n' + sep_time['text'] + '\n'
77 | return 1
78 | else:
79 | select_course_payload['sids'].append(course_code.group(1))
80 | return 0
81 |
82 |
83 | def select_separately(event):
84 | select_course_page = check_online()
85 | if select_course_page is None:
86 | return
87 |
88 | course_list = course_input_separate.get()
89 | course_list = course_list.split(',')
90 | for course in course_list:
91 | select_course_payload['sids'] = []
92 | if add_course_code_to_payload(course, select_course_page):
93 | continue
94 |
95 | select_result_page = post_data('http://jwxk.ucas.ac.cn/courseManage/saveCourse', select_course_payload)
96 | if select_result_page is None:
97 | log['text'] += course + ': 网页超时'+' \n ' + sep_time['text'] + '\n'
98 | else:
99 | generate_log(select_result_page)
100 |
101 | select_result['text'] = '选课完成'
102 |
103 |
104 | def select_together(event):
105 | select_course_page = check_online()
106 | if select_course_page is None:
107 | return
108 |
109 | course_list = course_input.get()
110 | course_list = course_list.split(',')
111 | select_course_payload['sids'] = []
112 | for course in course_list:
113 | add_course_code_to_payload(course, select_course_page)
114 |
115 | if len(select_course_payload['sids']) == 0:
116 | select_result['text'] = '课程代码均不可用'
117 | return
118 |
119 | select_result_page = post_data('http://jwxk.ucas.ac.cn/courseManage/saveCourse', select_course_payload)
120 | if select_result_page is None:
121 | select_result['text'] = '网页超时 没有进行选课'
122 | else:
123 | generate_log(select_result_page)
124 | select_result['text'] = '选课完成'
125 |
126 |
127 | def login(event):
128 | user = user_input.get()
129 | pwd = pwd_input.get()
130 | code = cert_code_input.get()
131 | login_payload = {'userName': user, 'pwd': pwd, 'certCode': code, 'sb': 'sb'}
132 |
133 | login_info['text'] = '正在登录'
134 | root.update_idletasks()
135 |
136 | page = post_data('http://sep.ucas.ac.cn/slogin', data=login_payload)
137 | if page is None:
138 | login_info['text'] = '网页超时 请重新登录'
139 | return
140 |
141 | pattern = re.compile(' (.+?)', re.S)
142 | try:
143 | name = re.search(pattern, page.text).group(1)
144 | except:
145 | login_info['text'] = '信息有误'
146 | return
147 |
148 | page = post_data('http://sep.ucas.ac.cn/portal/site/226/821')
149 | if page is None:
150 | login_info['text'] = '网页超时 请重新登录'
151 | return
152 |
153 | pattern = re.compile('Identity=([\w-]*)')
154 | try:
155 | iden = re.search(pattern, page.text).group(1)
156 | except:
157 | login_info['text'] = '没有成功匹配到Identity,请及时联系作者'
158 | return
159 |
160 | login_info['text'] = '正在跳转'
161 | root.update_idletasks()
162 |
163 | jump_payload = {'Identity': iden}
164 | page = post_data('http://jwxk.ucas.ac.cn/login', data=jump_payload)
165 | if page is None:
166 | login_info['text'] = '网页超时 请重新登录'
167 | return
168 |
169 | pattern = re.compile(' (.+?) \s*\(当前\)')
170 | try:
171 | student_number = re.search(pattern, page.text).group(1)
172 | student_number_payload = {'num': student_number}
173 | page = post_data('http://jwxk.ucas.ac.cn/doSelectNo', data=student_number_payload)
174 | if page is None:
175 | login_info['text'] = '网页超时 请重新登录'
176 | return
177 | except:
178 | pass
179 |
180 | page = post_data('http://jwxk.ucas.ac.cn/courseManage/main')
181 | if page is None:
182 | login_info['text'] = '网页超时 请重新登录'
183 | return
184 | pattern = re.compile('\?s=(.*?)";')
185 | select_course_s = re.search(pattern, page.text).group(1)
186 | pattern = re.compile('label for="id_(\d+)"')
187 | deptIds = re.findall(pattern, page.text)
188 | global select_course_payload
189 | select_course_payload = {'s': select_course_s, 'deptIds': deptIds}
190 | login_info['text'] = '登陆成功 ' + name
191 |
192 |
193 | def get_time():
194 | while True:
195 | try:
196 | current_time = requests.get('http://jwxk.ucas.ac.cn/courseManage/main', timeout=3)
197 | current_time = current_time.headers
198 | current_time = current_time['Date']
199 | hour = current_time[17:19]
200 | minute = current_time[20:22]
201 | second = current_time[23:25]
202 | hour = int(hour) + 8
203 | time_str = str(hour) + ':' + minute + ':' + second
204 | sep_time['text'] = time_str
205 | time.sleep(1)
206 | root.update_idletasks()
207 | except:
208 | pass
209 |
210 |
211 | def auto_select():
212 | global auto_working
213 | while True:
214 | if auto_working and login_info['text'] != '您已经掉线':
215 | select_separately(None)
216 | time.sleep(1)
217 |
218 |
219 | def auto_switch(event):
220 | global auto_working
221 | if auto_working == 0:
222 | tkinter.messagebox.showinfo(title='提示',
223 | message='1.请先使用“分开选”功能,确认提示信息为“超过限选人数”(而无其他错误)后再使用此功能\n'
224 | '2.此模式每1s自动进行一次“分开选”(温馨提示:持续过长有风险)\n'
225 | '3.如若中途掉线,需要自己手动重新登录')
226 | jianlou_switch['text'] = '停止'
227 | else:
228 | jianlou_switch['text'] = '捡漏'
229 | auto_working = 1 - auto_working
230 |
231 |
232 | def download_image_file(event):
233 | global sess
234 | sess = requests.session()
235 | sess.headers.update({'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4261.0 Safari/537.36'})
236 |
237 | login_info['text'] = ''
238 | try:
239 | html = sess.get('http://sep.ucas.ac.cn/changePic', timeout=3)
240 | except:
241 | login_info['text'] = '网页超时 请重新获取验证码'
242 | return
243 |
244 | fp = open("certcode.jpg", 'wb')
245 | fp.write(html.content)
246 | fp.close()
247 | global cert_photo
248 | cert_img = Image.open("certcode.jpg")
249 | cert_photo = ImageTk.PhotoImage(cert_img)
250 | show_pic['image'] = cert_photo
251 |
252 |
253 | if __name__ == "__main__":
254 | auto_working = 0
255 | login_check = 0
256 | root = tkinter.Tk()
257 | root.title("UCAS_course_grad 1.8 by wyf && YaoBIG QQ:751076061")
258 | root.geometry('620x640')
259 | root.resizable(width=False, height=False)
260 |
261 | sep_time = tkinter.Label(root, font=('Calibri', '10'))
262 | sep_time.grid(row=0, column=1, sticky=tkinter.E)
263 |
264 | thread_1 = threading.Thread(target=get_time)
265 | thread_1.setDaemon(True)
266 | thread_1.start()
267 |
268 | thread_2 = threading.Thread(target=auto_select)
269 | thread_2.setDaemon(True)
270 | thread_2.start()
271 |
272 | login_info = tkinter.Label(root, text='')
273 | login_info.grid(row=6, column=0, sticky=tkinter.W)
274 | login_info['font'] = ('Calibri', '14')
275 |
276 | select_result = tkinter.Label(root, text='')
277 | select_result.grid(row=9, sticky=tkinter.W)
278 | select_result['font'] = ('Calibri', '14')
279 |
280 | tkinter.Label(root, text='用户名(同sep)', font=('Calibri', '14')).grid(row=0, column=0, sticky=tkinter.W)
281 | user_input = tkinter.Entry(root)
282 | user_input.grid(row=1, column=0, sticky=tkinter.W)
283 | user_input['font'] = ('Calibri', '14')
284 | user_input['width'] = 30
285 |
286 | tkinter.Label(root, text='密码', font=('Calibri', '14')).grid(row=0, column=1, sticky=tkinter.W)
287 | pwd_input = tkinter.Entry(root)
288 | pwd_input['show'] = '*'
289 | pwd_input['width'] = 30
290 | pwd_input.grid(row=1, column=1, sticky=tkinter.W)
291 | pwd_input['font'] = ('Calibri', '14')
292 | pwd_input.bind('', login)
293 |
294 | get_pic = tkinter.Button(root, text='重新获取验证码')
295 | get_pic['width'] = 12
296 | get_pic.grid(row=5, column=1, sticky=tkinter.W)
297 | get_pic['font'] = ('Calibri', '14')
298 | get_pic.bind('', download_image_file)
299 |
300 | show_pic = tkinter.Label(root)
301 | show_pic.grid(row=5, column=1, sticky=tkinter.E)
302 | download_image_file(None)
303 |
304 | tkinter.Label(root, text='验证码', font=('Calibri', '14')).grid(row=2, column=0, sticky=tkinter.W)
305 |
306 | cert_code_input = tkinter.Entry(root)
307 | cert_code_input['width'] = 30
308 | cert_code_input.grid(row=5, column=0, sticky=tkinter.W)
309 | cert_code_input['font'] = ('Calibri', '14')
310 | cert_code_input.bind('', login)
311 |
312 | login_button = tkinter.Button(root, text='登 录')
313 | login_button['width'] = 6
314 | login_button['font'] = ('Calibri', '14')
315 | login_button.grid(row=6, column=1, sticky=tkinter.E)
316 | login_button.bind('', login)
317 |
318 | tkinter.Label(root, text='课程编码(一起选) 用逗号连接', font=('Calibri', '14')).grid(row=7, column=0, sticky=tkinter.W) # NOTE: 部分课程编号中有空格,请注意
319 | course_input = tkinter.Entry(root)
320 | course_input['width'] = 30
321 | course_input.grid(row=8, column=0, sticky=tkinter.W)
322 | course_input['font'] = ('Calibri', '14')
323 | course_input.bind('', select_together)
324 |
325 | tkinter.Label(root, text='课程编码(分开选) 用逗号连接', font=('Calibri', '14')).grid(row=7, column=1, sticky=tkinter.W)
326 | course_input_separate = tkinter.Entry(root)
327 | course_input_separate['width'] = 30
328 | course_input_separate.grid(row=8, column=1, sticky=tkinter.W)
329 | course_input_separate['font'] = ('Calibri', '14')
330 | course_input_separate.bind('', select_separately)
331 |
332 | course_choose = tkinter.Button(root, text='一起选')
333 | course_choose.bind('', select_together)
334 | course_choose['font'] = ('Calibri', '14')
335 | course_choose['width'] = 6
336 | course_choose.grid(row=9, column=0, sticky=tkinter.E)
337 |
338 | course_choose = tkinter.Button(root, text='分开选')
339 | course_choose.bind('', select_separately)
340 | course_choose['font'] = ('Calibri', '14')
341 | course_choose['width'] = 6
342 | course_choose.grid(row=9, column=1, sticky=tkinter.E)
343 |
344 | jianlou_switch = tkinter.Button(root, text='捡 漏')
345 | jianlou_switch.bind('', auto_switch)
346 | jianlou_switch['font'] = ('Calibri', '14')
347 | jianlou_switch['width'] = 6
348 | jianlou_switch.grid(row=9, column=1, sticky=tkinter.W)
349 |
350 | tkinter.Label(root, text='Log:', font=('Calibri', '14')).grid(row=11, column=0, sticky=tkinter.W)
351 | log = tkinter.Label(root, anchor='nw', justify='left', background='white', relief='sunken', height=21, width=50,
352 | borderwidth=2)
353 | log.grid(row=12, column=0, sticky=tkinter.W)
354 | log['font'] = ('Calibri', '9')
355 |
356 | tkinter.Label(root, text='Log_Success:', font=('Calibri', '14')).grid(row=11, column=1, sticky=tkinter.W)
357 | log_success = tkinter.Label(root, anchor='nw', justify='left', background='white', relief='sunken', height=21,
358 | width=50, borderwidth=2)
359 | log_success.grid(row=12, column=1, sticky=tkinter.W)
360 | log_success['font'] = ('Calibri', '9')
361 |
362 | root.mainloop()
363 |
364 |
--------------------------------------------------------------------------------
/dist/UCAS_course.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WuYunfan/UCAS_course_script/6c570cf694501df43f30e8735e5b7c6719ae3c16/dist/UCAS_course.exe
--------------------------------------------------------------------------------