#!/usr/bin/env python # -*- encoding: utf-8 -*- ''' @Contact : liuyuqi.gov@msn.cn @Time : 2022/05/31 01:04:55 @License : Copyright © 2017-2022 liuyuqi. All Rights Reserved. @Desc : cuit.edu.cn 自动选课 ''' import platform from auto_cuit.libs.json_conf import JsonConf from auto_cuit import api import requests import os import sys import re import json import time import random class Cuit(object): def __init__(self, configPath="conf/config.josn"): self.sess = requests.session() self.conf = JsonConf(configPath) self.sess.cookies = self.conf.data['cookies'] self.sess.headers = { "X-Requested-With": "XMLHttpRequest", "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.0 Safari/537.36 Edg/84.0.521.0" } def run(self): profiledId = self.conf.data['profiled_id'] courseName = self.conf.data['course_name'] # 验证码 cnt = 0 while True: pic = self.getCaptcha() ocrResult = self.postOCRPic(pic) print('OCR: ' + ocrResult['result']) checkResult = self.checkCaptcha(ocrResult['result'], profiledId) if checkResult: break cnt += 1 time.sleep(0.5) if cnt % 5 == 0: print('验证码错误次数过多, 等待5秒') time.sleep(5) print('验证码检测通过,等待1秒') time.sleep(1) # 检测开放状态 print('获取lessonId') lessonId = self.courseName2Id(profiledId, courseName) if lessonId == None: print('没有找到相关课程:' + courseName) exit(1) print('检测选课开放状态') cnt = 0 while True: if self.isAvailable(ocrResult['result'], profiledId): break pass cnt += 1 print('没有到选课时间,等待5秒 - ' + str(cnt)) time.sleep(5) # 抢课 print('开始抢课') i = 0 while True: i += 1 print(i) if self.fuckCourse(str(profiledId), str(lessonId)): break time.sleep(0.5) if i >= 20: i = 0 if platform.system().lower() == 'linux': os.system("clear") elif platform.system().lower() == 'windows': os.system("cls") pass pass pass def fuckCourse(self, profiledId, lessonId): try: body = { "optype": "true", "operator0": lessonId + ":true:0", "lesson0": lessonId, "schLessonGroup_" + lessonId: "undefined" } req = requests.post(api.chooseCourse % profiledId, data=body, timeout=5, allow_redirects=False) req.encoding = 'utf-8' html = req.text ret = re.search(r"margin:auto;\">\n\t\t\t\t(.*)<\/br>", html) if ret == None: print("cookie过期") exit(-1) pass print(ret.group(1)) req.close() if '成功' in ret.group(1): print('get') return True except Exception as err: print("出错") print(err) return False pass pass def getCaptcha(self): try: picReq = self.sess.get(url=api.getCaptcha, timeout=5) except Exception as err: print(err) return picReq.content def postOCRPic(self, pic): url = self.ocrServer files = {'captcha': pic} data = { 'enctype': 'multipart/form-data', 'name': 'captcha' } ocrReq = requests.post(url=url, data=data, files=files) return json.loads(ocrReq.content) def checkCaptcha(self, captcha, profiledId): data = { 'captcha_response': captcha, 'electionProfile.id': profiledId } try: checkReq = requests.post( url=api.checkCode, data=data, allow_redirects=False, timeout=5) except Exception as err: logger.error(err) # print(checkReq.text) # 未登录与验证码错误都是302,但Location去向不同 if checkReq.status_code == 200: return True elif 'sso' in checkReq.headers['Location']: # 转到统一登录中心 print('cookie失效!!!') exit(1) return False def isAvailable(self, captcha, profiledId): ''' 检测登录状态 ''' data = { 'captcha_response': captcha, 'electionProfile.id': profiledId } try: checkReq = self.sess.post( url=api.checkCode, data=data, allow_redirects=False, timeout=5) # 未登录与验证码错误都是302,但Location去向不同 if checkReq.status_code == 200: return '不在选课时间内' not in checkReq.text elif 'sso' in checkReq.headers['Location']: # 转到统一登录中心 print('cookie失效') False except Exception as err: logger.error(err) return False return False def courseName2Id(self, profileId, courseName): try: courseListReq = self.sess.get( url=api.getCourseList % str(profileId), allow_redirects=False, timeout=5) except Exception as err: print(err) courseList = courseListReq.text jsData = execjs.compile(courseList) lessonJSONs = jsData.eval('lessonJSONs') # print(lessonJSONs) for lesson in lessonJSONs: if courseName in lesson['name']: return lesson['id'] return None