diff --git a/__pycache__/get_info.cpython-310.pyc b/__pycache__/get_info.cpython-310.pyc index 4993b54..4c586a4 100644 Binary files a/__pycache__/get_info.cpython-310.pyc and b/__pycache__/get_info.cpython-310.pyc differ diff --git a/__pycache__/kill_course.cpython-310.pyc b/__pycache__/kill_course.cpython-310.pyc index 487713a..d479e03 100644 Binary files a/__pycache__/kill_course.cpython-310.pyc and b/__pycache__/kill_course.cpython-310.pyc differ diff --git a/__pycache__/single_course.cpython-310.pyc b/__pycache__/single_course.cpython-310.pyc index d41db22..a3b6f98 100644 Binary files a/__pycache__/single_course.cpython-310.pyc and b/__pycache__/single_course.cpython-310.pyc differ diff --git a/course_info.json b/course_info.json index 6331538..fa5bdb7 100644 --- a/course_info.json +++ b/course_info.json @@ -1,157 +1 @@ -{ - "7367": { - "rate": 100, - "type": "\u5fc5\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "7366": { - "rate": 100, - "type": "\u5fc5\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "7033": { - "rate": 100, - "type": "\u5fc5\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "7517": { - "rate": 100, - "type": "\u5fc5\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "7032": { - "rate": 100, - "type": "\u5fc5\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "7516": { - "rate": 100, - "type": "\u5fc5\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "7031": { - "rate": 100, - "type": "\u5fc5\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "7515": { - "rate": 100, - "type": "\u5fc5\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "6349": { - "rate": 100, - "type": "\u5fc5\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "7436": { - "rate": 100, - "type": "\u5fc5\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "6937": { - "rate": 100, - "type": "\u57f9\u8bad", - "status": "\u672a\u8bc4\u5206" - }, - "6938": { - "rate": 100, - "type": "\u57f9\u8bad", - "status": "\u672a\u8bc4\u5206" - }, - "6991": { - "rate": 15, - "type": "\u57f9\u8bad", - "status": "\u672a\u5b66\u5b8c" - }, - "6992": { - "rate": 100, - "type": "\u57f9\u8bad", - "status": "\u5df2\u5b66\u5b8c" - }, - "6993": { - "rate": 100, - "type": "\u57f9\u8bad", - "status": "\u5df2\u5b66\u5b8c" - }, - "6995": { - "rate": 100, - "type": "\u57f9\u8bad", - "status": "\u5df2\u5b66\u5b8c" - }, - "7006": { - "rate": 100, - "type": "\u57f9\u8bad", - "status": "\u5df2\u5b66\u5b8c" - }, - "7007": { - "rate": 100, - "type": "\u57f9\u8bad", - "status": "\u5df2\u5b66\u5b8c" - }, - "7010": { - "rate": 100, - "type": "\u57f9\u8bad", - "status": "\u5df2\u5b66\u5b8c" - }, - "7011": { - "rate": 100, - "type": "\u57f9\u8bad", - "status": "\u5df2\u5b66\u5b8c" - }, - "7554": { - "rate": 100, - "type": "\u9009\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "7553": { - "rate": 100, - "type": "\u9009\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "7552": { - "rate": 100, - "type": "\u9009\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "7551": { - "rate": 100, - "type": "\u9009\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "7550": { - "rate": 100, - "type": "\u9009\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "7549": { - "rate": 100, - "type": "\u9009\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "7548": { - "rate": 100, - "type": "\u9009\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "7547": { - "rate": 100, - "type": "\u9009\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "7546": { - "rate": 100, - "type": "\u9009\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "7545": { - "rate": 100, - "type": "\u9009\u4fee", - "status": "\u5df2\u5b66\u5b8c" - }, - "7564": { - "rate": 100, - "type": "\u9009\u4fee", - "status": "\u5df2\u5b66\u5b8c" - } -} \ No newline at end of file +{"6349": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7436": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7367": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7366": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7033": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7517": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7032": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7516": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7031": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7515": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "6937": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u5df2\u5b66\u5b8c"}, "6938": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u672a\u8bc4\u5206"}, "6991": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u672a\u8bc4\u5206"}, "6992": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u5df2\u5b66\u5b8c"}, "6993": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u5df2\u5b66\u5b8c"}, "6995": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u5df2\u5b66\u5b8c"}, "7006": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u5df2\u5b66\u5b8c"}, "7007": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u5df2\u5b66\u5b8c"}, "7010": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u5df2\u5b66\u5b8c"}, "7011": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u5df2\u5b66\u5b8c"}, "7554": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7553": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7552": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7551": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7550": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7549": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7548": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7547": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7546": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7545": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7564": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}} \ No newline at end of file diff --git a/demo.py b/demo.py index 4e3b81f..2b61483 100644 --- a/demo.py +++ b/demo.py @@ -1,4 +1,10 @@ -from DrissionPage import ChromiumPage -from DrissionPage.common import * -page = ChromiumPage() -page.ele('tag:a@@text():是').click() \ No newline at end of file +from collections import * +import json +info = json.load(open('course_info.json', 'r')) +cnt = defaultdict(list) +new_cnt = defaultdict(list) +for k, v in info.items(): + new_cnt[v['type']].append((k,v['rate'],v['status'])) # 课程类型作为键,课程id作为值 +print(new_cnt) +for k,v in new_cnt.items(): + print(k,v) \ No newline at end of file diff --git a/get_info.py b/get_info.py index 9ef8ae8..b0f73b1 100644 --- a/get_info.py +++ b/get_info.py @@ -4,35 +4,63 @@ from collections import * import time import json from loguru import logger +import subprocess # http://hnqmgc.17el.cn/grzx/ -def get_info(): - # 创建页面对象,并启动或接管浏览器 +# 单独实现登录操作 +def login(first:bool=True): + if not first: + return + # 先检查当前页面是否已经登录 page = WebPage() - # 跳转到登录页面 try: - page.get('http://hnqmgc.17el.cn/grzx/',retry=5,timeout=5,interval=1) + if page.ele('tag:div@@text():欢迎您,',timeout=3): + logger.info('当前页面已登录') + return except BaseException: - logger.error('网络连接失败') + logger.info('准备登录') + if first: + try: + page.get('http://hnqmgc.17el.cn/grzx/',retry=5,timeout=5,interval=1) + except BaseException: + logger.error('网络连接失败') - # 定位到账号文本框,获取文本框元素 - ele = page.ele('#userName') # #的意思是通过id定位元素 - # 输入对文本框输入账号 - ele.input('51140220050507901X') - # 定位到密码文本框并输入密码 - page.ele('#password').input('hnqm123456') - # 定位到验证码文本框并输入验证码 - inpcode = page.ele('#yzcode').text # 湖南青马太可爱了吧,验证码居然直接放在页面源码里:) - page.ele('#inpcode').input(inpcode) - # 点击登录按钮 - page.ele('#btnLogin').click() - # 进入课程页面 - page.ele('.wxtsBox-button').click() # 关闭提示页面 - page.ele('#login_btn').click() - page.ele('@value=进入个人中心').click() + # 定位到账号文本框,获取文本框元素 + ele = page.ele('#userName') # #的意思是通过id定位元素 + # 输入对文本框输入账号 + ele.input('51140220050507901X') + # 定位到密码文本框并输入密码 + page.ele('#password').input('hnqm123456') + # 定位到验证码文本框并输入验证码 + inpcode = page.ele('#yzcode').text # 湖南青马太可爱了吧,验证码居然直接放在页面源码里:) + page.ele('#inpcode').input(inpcode) + # 点击登录按钮 + page.ele('#btnLogin').click() + page.wait.new_tab(3) + # 进入课程页面 + try: + if page.ele('@onclick=cha()',timeout=3): + page.ele('@onclick=cha()').click() + # + elif page.ele('tag:img@@style=width: 25px;height: 25px;',timeout=3): + page.ele('tag:img@@style=width: 25px;height: 25px;').click() + except BaseException: + logger.error('不能进入课程页面') + subprocess.run(["python", __file__]) + exit() + page.ele('#login_btn').click() + page.ele('@value=进入个人中心').click() +def get_info(first:bool=True): + # 创建页面对象,并启动或接管浏览器 + page = WebPage() + # 登录 + login(first) # 提取课程信息 time.sleep(2) - page.ele('@value=0').click() + if not first: + page.refresh() + time.sleep(2) + page.ele('@value=0',timeout=3).click() # 获取总页数 course_info = {} #
1 / 4
diff --git a/kill_course.py b/kill_course.py index 48f8aad..2444f02 100644 --- a/kill_course.py +++ b/kill_course.py @@ -12,7 +12,10 @@ def kill_course(again:bool=False): for k, v in info.items(): if v['rate'] < 100: cnt[v['type']].append((k,v['rate'])) # 课程类型作为键,课程id作为值 - print(cnt) + logger.info('{}'.format(cnt)) + if not cnt: + logger.info('所有课程均已完成') + return # 按必修-选秀-专题-培训执行刷课 must = cnt['必修'] elective = cnt['选修'] diff --git a/main.py b/main.py index e7644b9..ae08881 100644 --- a/main.py +++ b/main.py @@ -4,6 +4,9 @@ from collections import * from loguru import logger import subprocess from typing import * +from DrissionPage import ChromiumPage +from DrissionPage.common import * +import time # 获取课程信息 get_info() # 执行刷课 @@ -15,11 +18,10 @@ kill_course() 1. 对于必修课存在3种情况:未完成,已完成,未答题 2. 对于其他课存在3种情况:未完成,已完成,未评分 ''' - # 重新获取课程信息 def new_info() -> DefaultDict[str, List[Tuple[str,int,str]]]: - get_info() - new_info = json.load(open('info.json','r')) + get_info(first=False) + new_info = json.load(open('course_info.json','r')) # 读取各个类别的课程状态 new_cnt = defaultdict(list) for k, v in new_info.items(): @@ -42,20 +44,44 @@ new_cnt = new_info() not_judged = [] not_quiz = [] for k, v in new_cnt.items(): - if v['status'] == '已完成': - continue - if v['status'] == '未评分': - not_judged.append(k) - else: - not_quiz.append(k) + for i in v: + if i[2] == '未评分': + not_judged.append((i[0],k)) + elif i[2] == '未答题': + not_quiz.append(i[0],k) # 展示提示信息 for i in not_judged: logger.warning('存在未评分的课程:{}'.format(i)) # 实现自动评分 -def auto_judge(course_id:str) -> None: +def auto_judge(course_id:str,course_type:str) -> None: + # 根据课程类型和id进行定位 + j_page = ChromiumPage() # 接管当前页面 + # 判定课程类别 + if course_type == '必修': + j_page.ele('@value=1').click() + elif course_type == '选修': + j_page.ele('@value=2').click() + elif course_type == '专题': + j_page.ele('@value=4').click() + elif course_type == '培训': + j_page.ele('@value=5').click() + time.sleep(1) + trs = j_page.ele('#tbody').eles('tag:tr') + for tr in trs: + # 鉴别课程序号 + if tr.ele('tag:td').text.split('\t')[0] == course_id: + # 进入评分页面 + tr.ele('tag:button@@text():进入评分').click() + j_page.ele('x://*[@id="gradeDetail_score"]/label[1]/input').click() + j_page.ele('tag:a@@text():保存').click() + time.sleep(1) pass +print(not_judged) +# 实现自动评分 for i in not_judged: - logger.warning('存在未答题的课程:{}'.format(i)) + auto_judge(i[0],i[1]) + logger.info('已完成对课程:{}的评分'.format(i[0])) # 实现自动答题 -pass \ No newline at end of file +def auto_quiz(course_id:str) -> None: + pass \ No newline at end of file diff --git a/single_course.py b/single_course.py index 170db38..e1db538 100644 --- a/single_course.py +++ b/single_course.py @@ -82,17 +82,18 @@ def one_course(cid:str,ctype:str,crate:int,again:bool=False): tab.ele('tag:a@@text():是').click() except: pass - # 有时候没有弹窗提示,用以下方式手动检测 - for i in l: - if i != 100: - tab.ele('#normalModel_nodeList').eles('tag:div')[l.index(i)].click() - time.sleep(1) - try: - if tab.ele('c:#normalModel_video > xg-start > div.xgplayer-icon-play > svg > path',timeout=2): - tab.ele('c:#normalModel_video > xg-start > div.xgplayer-icon-play > svg > path').click() - except: - pass - time.sleep(60) # 每次监测间隔60秒 + finally: + # 有时候没有弹窗提示,用以下方式手动检测 + for i in l: + if i != 100: + tab.ele('#normalModel_nodeList').eles('tag:div')[l.index(i)+1].click() + time.sleep(1) + try: + if tab.ele('c:#normalModel_video > xg-start > div.xgplayer-icon-play > svg > path',timeout=2): + tab.ele('c:#normalModel_video > xg-start > div.xgplayer-icon-play > svg > path').click() + except: + pass + time.sleep(60) # 每次监测间隔60秒 break # なぜここにbreakがいるのですか?あかしいなあ。 if __name__ == '__main__':