new file: __pycache__/get_info.cpython-310.pyc

new file:   __pycache__/kill_course.cpython-310.pyc
	new file:   __pycache__/single_course.cpython-310.pyc
	modified:   course_info.json
	modified:   demo.py
	new file:   file.log
	modified:   get_info.py
	modified:   kill_course.py
	new file:   kill_quiz.py
	new file:   main.py
	modified:   single_course.py
main
JesterHey 1 year ago
parent 145bd5b71a
commit fffbd89ffd

@ -1 +1 @@
{"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"}, "7367": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "6937": {"rate": 0, "type": "\u57f9\u8bad", "status": "\u672a\u5b66\u5b8c"}, "6938": {"rate": 0, "type": "\u57f9\u8bad", "status": "\u672a\u5b66\u5b8c"}, "6991": {"rate": 0, "type": "\u57f9\u8bad", "status": "\u672a\u5b66\u5b8c"}, "6992": {"rate": 68, "type": "\u57f9\u8bad", "status": "\u672a\u5b66\u5b8c"}, "6993": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u672a\u8bc4\u5206"}, "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": 0, "type": "\u9009\u4fee", "status": "\u672a\u5b66\u5b8c"}} {"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": 0, "type": "\u57f9\u8bad", "status": "\u672a\u5b66\u5b8c"}, "6938": {"rate": 0, "type": "\u57f9\u8bad", "status": "\u672a\u5b66\u5b8c"}, "6991": {"rate": 9, "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"}}

@ -1,4 +1,6 @@
import json from loguru import logger
info = json.load(open('course_info.json', 'r')) # 自定义日志格式
print(info) logger.add("file.log", format="{time} {level} {message}", level="DEBUG")
logger.debug("这是一条具有自定义格式的日志信息")

@ -0,0 +1 @@
2024-03-10T12:13:35.955107+0800 DEBUG 这是一条具有自定义格式的日志信息

@ -3,14 +3,17 @@ from DrissionPage.common import *
from collections import * from collections import *
import time import time
import json import json
from loguru import logger
# http://hnqmgc.17el.cn/grzx/ # http://hnqmgc.17el.cn/grzx/
def decode(s): def get_info():
return json.loads('"%s"' %s) # 由于页面源码中的json字符串是单引号包裹的所以需要转换成双引号包裹的json字符串
# 创建页面对象,并启动或接管浏览器 # 创建页面对象,并启动或接管浏览器
page = WebPage() page = WebPage()
# 跳转到登录页面 # 跳转到登录页面
try:
page.get('http://hnqmgc.17el.cn/grzx/',retry=5,timeout=5,interval=1) page.get('http://hnqmgc.17el.cn/grzx/',retry=5,timeout=5,interval=1)
except BaseException:
logger.error('网络连接失败')
# 定位到账号文本框,获取文本框元素 # 定位到账号文本框,获取文本框元素
ele = page.ele('#userName') # #的意思是通过id定位元素 ele = page.ele('#userName') # #的意思是通过id定位元素
@ -46,7 +49,7 @@ for i in range(total_page):
course_type = cur_info[2] # 课程类型 course_type = cur_info[2] # 课程类型
course_rate = int(cur_info[3][:-1]) # 课程完成百分比 course_rate = int(cur_info[3][:-1]) # 课程完成百分比
course_status = cur_info[4] # 课程完成状态(是否完成习题/评价) course_status = cur_info[4] # 课程完成状态(是否完成习题/评价)
print(course_id, course_rate, course_status) logger.info('课程id:{}|课程类型:{}|课程完成率:{}|课程完成状态:{}'.format(course_id,course_type,course_rate,course_status))
# 存放到字典中 # 存放到字典中
course_info[course_id] = {'rate': course_rate,'type': course_type,'status': course_status} course_info[course_id] = {'rate': course_rate,'type': course_type,'status': course_status}
if i != total_page - 1: if i != total_page - 1:
@ -57,3 +60,5 @@ print(len(course_info))
with open('course_info.json', 'w') as f: with open('course_info.json', 'w') as f:
json.dump(course_info, f) json.dump(course_info, f)
if __name__ == '__main__':
get_info()

@ -1,15 +1,17 @@
from DrissionPage import ChromiumPage from DrissionPage import ChromiumPage
from DrissionPage.common import * from DrissionPage.common import *
from collections import * from collections import *
import time
import json import json
from single_course import one_course
from loguru import logger
def kill_course():
# 统计课程完成情况 # 统计课程完成情况
cnt = defaultdict(list) cnt = defaultdict(list)
# 读取课程信息 # 读取课程信息
info = json.load(open('course_info.json', 'r')) info = json.load(open('course_info.json', 'r'))
for k, v in info.items(): for k, v in info.items():
if v['rate'] < 100: if v['rate'] < 100:
cnt[v['type']].append(k) cnt[v['type']].append((k,v['rate'])) # 课程类型作为键课程id作为值
print(cnt) print(cnt)
# 按必修-选秀-专题-培训执行刷课 # 按必修-选秀-专题-培训执行刷课
must = cnt['必修'] must = cnt['必修']
@ -18,22 +20,21 @@ special = cnt['专题']
train = cnt['培训'] train = cnt['培训']
while must or elective or special or train: while must or elective or special or train:
if must: if must:
course_id = must.pop() course_info = must.pop()
print('Kill course:', course_id) logger.info('当前刷课序号:{}'.format(course_info[0]))
# 执行刷课 one_course(course_info[0], '必修', course_info[1])
# ...
if elective: if elective:
course_id = elective.pop() course_info = elective.pop()
print('Kill course:', course_id) logger.info('当前刷课序号:{}'.format(course_info[0]))
# 执行刷课 one_course(course_info[0], '选修', course_info[1])
# ...
if special: if special:
course_id = special.pop() course_info = special.pop()
print('Kill course:', course_id) logger.info('当前刷课序号:{}'.format(course_info[0]))
# 执行刷课 one_course(course_info[0], '专题', course_info[1])
# ...
if train: if train:
course_id = train.pop() course_info = train.pop()
print('Kill course:', course_id) logger.info('当前刷课序号:{}'.format(course_info[0]))
# 执行刷课 one_course(course_info[0], '培训', course_info[1])
# ...
if __name__ == '__main__':
kill_course()

@ -0,0 +1,5 @@
# 实现答题和评分
'''
检测课程状态是否存在未评价或者未答题状态
'''
from get_info import get_info

@ -0,0 +1,6 @@
from get_info import get_info
# 获取课程信息
get_info()
# 执行刷课
from kill_course import kill_course
kill_course()

@ -1,15 +1,21 @@
from DrissionPage import ChromiumPage from DrissionPage import ChromiumPage
from DrissionPage.common import * from DrissionPage.common import *
import time import time
from loguru import logger
# 实现单个课程的刷课逻辑 # 实现单个课程的刷课逻辑
def one_course(cid:str,ctype:str,crate:int):
''' '''
cid: 课程id
ctype: 课程类型
crate: 课程总体完成率
----------------------
接受一个课程id,执行刷课 接受一个课程id,执行刷课
1. 跳转到对应课程页面 1. 跳转到对应课程页面
2. 进入相应的课程界面 2. 进入相应的课程界面
3. 循环检验课程是否完成 3. 循环检验课程是否完成
4. 完成当前课程后退出 4. 完成当前课程后退出
''' '''
def one_course(cid:str,ctype:str,crate:int):
# 接管浏览器 # 接管浏览器
cur_page = ChromiumPage() cur_page = ChromiumPage()
# 判定课程类别 # 判定课程类别
@ -45,25 +51,37 @@ def one_course(cid:str,ctype:str,crate:int):
<div id="normalModel_nodeList" style="max-height:550px;overflow:auto;"> <div id="normalModel_nodeList" style="max-height:550px;overflow:auto;">
<div class="item-title selected" id="node_27817"><div class="courseName" title="活的马克思主义(上)" style="font-size:13px;">活的马克思主义()</div><span class="progressBar progress" style="font-size:12px;" id="progress_27817"><img id="progress_27817_percentImage" src="/js/axsProgress/images/percentImage.png" alt="100" style="width: 70px;height:12px;background-position: -50px 50%;background-image: url(/js/axsProgress/images/percentImage_back1.png);padding: 0;margin: 0;" class="percentImage" title="100%"> <span id="progress_27817_percentText" class="percentText" style="font-size:13px;">100%</span></span></div><div class="item-title" id="node_27821"><div class="courseName" title="活的马克思主义(下)" style="font-size:13px;">活的马克思主义()</div><span class="progressBar progress" style="font-size:12px;" id="progress_27821"><img id="progress_27821_percentImage" src="/js/axsProgress/images/percentImage.png" alt="100" style="width: 70px;height:12px;background-position: -50px 50%;background-image: url(/js/axsProgress/images/percentImage_back1.png);padding: 0;margin: 0;" class="percentImage" title="100%"> <span id="progress_27821_percentText" class="percentText" style="font-size:13px;">100%</span></span></div></div> <div class="item-title selected" id="node_27817"><div class="courseName" title="活的马克思主义(上)" style="font-size:13px;">活的马克思主义()</div><span class="progressBar progress" style="font-size:12px;" id="progress_27817"><img id="progress_27817_percentImage" src="/js/axsProgress/images/percentImage.png" alt="100" style="width: 70px;height:12px;background-position: -50px 50%;background-image: url(/js/axsProgress/images/percentImage_back1.png);padding: 0;margin: 0;" class="percentImage" title="100%"> <span id="progress_27817_percentText" class="percentText" style="font-size:13px;">100%</span></span></div><div class="item-title" id="node_27821"><div class="courseName" title="活的马克思主义(下)" style="font-size:13px;">活的马克思主义()</div><span class="progressBar progress" style="font-size:12px;" id="progress_27821"><img id="progress_27821_percentImage" src="/js/axsProgress/images/percentImage.png" alt="100" style="width: 70px;height:12px;background-position: -50px 50%;background-image: url(/js/axsProgress/images/percentImage_back1.png);padding: 0;margin: 0;" class="percentImage" title="100%"> <span id="progress_27821_percentText" class="percentText" style="font-size:13px;">100%</span></span></div></div>
''' '''
l = []
while 1: while 1:
# todo:想要加一个定时刷新的功能方便释放内存 # todo:想要加一个定时刷新的功能方便释放内存
watch_rates = tab.ele('#normalModel_nodeList').eles('tag:span') watch_rates = tab.ele('#normalModel_nodeList').eles('tag:span')
l = []
for watch_rate in watch_rates: for watch_rate in watch_rates:
l.append(int(watch_rate.text[:-1])) l.append(int(watch_rate.text[:-1]))
# 取偶数索引 # 取偶数索引
l = l[::2] l = l[::2]
n = len(l) infol = [str(i)+'%' for i in l]
logger.info('当前各个视频完成率:{}'.format(infol))
if l == [100]*len(l): if l == [100]*len(l):
# 关闭当前标签页 # 关闭当前标签页
logger.warning('当前课程已完成,当前标签页即将关闭')
time.sleep(1)
cur_page.close_tabs(tabs_or_ids=[tab]) cur_page.close_tabs(tabs_or_ids=[tab])
break
''' '''
由于视频播完后会自动暂停所以需要检测是否播放完毕以准备下一步操作 由于视频播完后会自动暂停所以需要检测是否播放完毕以准备下一步操作
解决方案检测列表中首个不是0的元素的索引根据索引点击对应的视频并尝试检测是否有播放按钮来区分正在播放和播放完毕 解决方案:检测列表中首个不是100的元素的索引,根据索引点击对应的视频,并尝试检测是否有播放按钮来区分正在播放和播放完毕
''' '''
# 睡觉了,明天继续:) 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秒 time.sleep(60) # 每次监测间隔60秒
break break # なぜここにbreakがいるのですかあかしいなあ。
if __name__ == '__main__': if __name__ == '__main__':
one_course('6992','培训',68) one_course('6992','培训',68)
Loading…
Cancel
Save