项目地址
Elevenlong1101/script-for-yuketang: selenium 简单实现雨课堂刷课,无需配置浏览器驱动,一键启用 (github.com)
登陆过程实现
由于作者太懒了,直接time.sleep()手动扫码
准备工作
1 2 3 4 5 6 7 8 9 10 11 12 13
| print("本脚本仅支持雨课堂平台\n")
print("牛魔雨课堂不得好死!!!\n")
name = input("请输入您想刷的课程名称:\n")
time.sleep(2)
print("接下来请在弹出的浏览器页面中扫码登陆,登陆后等待一段时间程序会自动开始运行\n")
print("想要退出刷课,只要退出浏览器窗口即可\n")
time.sleep(2)
|
各种输入输出,方便他人进行使用
隐藏selenium特征
1 2 3 4 5 6 7 8 9 10 11 12
| option = webdriver.EdgeOptions() # 创建浏览器设置实例 option.add_experimental_option('excludeSwitches', ['enable-automation']) # 禁止显示浏览器上方“chrome正受自动测试软件控制”字样 prefs = {'credentials_enable_service': False, 'profile.password_manager_enabled': False} option.add_experimental_option('prefs', prefs) option.add_argument('--disable-blink-features=AutomationControlled') # 隐藏windows.navigator.driver参数,通常为undefined 使用selenium则为true option.add_argument('--mute-audio') # 可选 静音启动浏览器 option.binary_location = 'selenium\edge117\msedge.exe' # 可选 配置浏览器启动位置
|
创建浏览器实例
1 2 3 4 5 6 7
| s = Service("selenium\msedgedriver117.exe") driver = webdriver.Edge(service= s,options= option) # 创建浏览器实例以及配置一下浏览器驱动位置 driver.get("https://xxxxx.yuketang.cn/web")
# 接下来开始登陆 time.sleep(10)# 给时间扫码
|
要注意的是,以上配置浏览器启动位置和浏览器驱动位置都应该注意一下相对路径,最好直接在vscode里面直接右键,复制相对路径,不要像我一样看了一下午如何配置浏览器驱动发现其实是相对位置写错了。。。md我花了五个小时
找到需要刷的课程
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| tab_student = driver.find_element(By.ID, 'tab-student') # 找到所有课程按钮的元素 tab_student.click() # 点击跳转到所有课程 time.sleep(1) # 等待加载 class_btn = driver.find_element(By.XPATH, f'//*[@id="pane-student"]//h1[contains(text(),{name})]') # 根据开头输入的名字找到要刷的课程 class_btn.click() # 点击进入 grade = driver.find_element(By.XPATH, '//div[@id="tab-student_school_report"]/span') grade.click() time.sleep(1) # 进入课程成绩单页面
|
这里注意,基本上所有涉及到刷新,加载等操作的地方都要sleep一下,或者直接隐式等待,主要取决于使用者的网速如何,否则会花费大量时间去排错。。。又是一个小时md
由于在课程主页面直接开刷会出问题(纯纯就是垃圾某课堂网页版没写好出的bug,吐槽一下,上课数量多了之后课程完成状态居然不显示。。。),所以多写两行跳转到成绩单页面再开始刷
开始刷课
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
| def study():
lessons = driver.find_elements(By.XPATH, '//li[@class="study-unit"]') # 找到课程列表 for lesson in lessons:
statistic = lesson.find_element(By.CSS_SELECTOR, 'div.complete-td span').text # 读取课程完成状态 if statistic == "已完成" or statistic == "已发言" or statistic == "未发言" or statistic == "未开始":
continue # 判断课程状态
else:
lesson_btn = lesson.find_element(By.CSS_SELECTOR, '.name-text')
driver.execute_script("$(arguments[0]).click()", lesson_btn)# 点击进入课程按钮 time.sleep(2)
driver.switch_to.window(driver.window_handles[-1])# 切换到课程窗口
#volume_btn = driver.find_element(By.XPATH, '//xt-icon')
#driver.execute_script("$(arguments[0]).click()", volume_btn)# 静音播放
finish_bar = driver.find_element(By.XPATH, '//span[@class="text"]').text
while finish_bar != "完成度:100%":
time.sleep(5)
finish_bar = driver.find_element(By.XPATH, '//span[@class="text"]').text# 每五秒刷新状态值
driver.close()
driver.switch_to.window(driver.window_handles[0])# 关闭刷课窗口并回到成绩单窗口 driver.refresh()# 刷新窗口获得课程完成状态
time.sleep(1)
grade = driver.find_element(By.XPATH, '//div[@id="tab-student_school_report"]/span')
grade.click()
time.sleep(1)# 点击转换到成绩单窗口
study() study()
|
总结
刷课部分倒没什么含金量,主要是各种细节很让人难受,例如文件的相对路径,浏览器的配置等等,很让人难受,整体写下来虽然磕磕绊绊,但也算有了结果,第一次写出来的东西,也不算完美吧,其实主要时间都花在解决乐色某课堂网页版的bug上了。。。
学到了很多
完整代码
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
| # 雨课堂刷课脚本2.0 不同思路进行重构
# 学习:静音开启浏览器
# 学习:切换窗口
# 学习:根据文本定位
# 学习:文本输入
# 学习:要取相对路径不要自己写,直接复制就好了!!!驱动和浏览器路径写错selenium不会报错,只会找默认路径的驱动和浏览器!
# 学习:导包的时候要注意路径问题,写的是edge还是chrome
# 学习:在哪里运行这个文件也很重要,这关系到文件中需要读取的文件的相对路径能否被找到
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.edge.service import Service
import time
# 事先声明
print("本脚本仅支持雨课堂平台\n")
print("牛魔雨课堂不得好死!!!\n")
name = input("请输入您想刷的课程名称:\n")
time.sleep(2)
print("接下来请在弹出的浏览器页面中扫码登陆,登陆后等待一段时间程序会自动开始运行\n")
print("想要退出刷课,只要退出浏览器窗口即可\n")
time.sleep(2)
# 隐藏特征
option = webdriver.EdgeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
prefs = {'credentials_enable_service': False, 'profile.password_manager_enabled': False}
option.add_experimental_option('prefs', prefs)
option.add_argument('--disable-blink-features=AutomationControlled')
option.add_argument('--mute-audio')
option.binary_location = 'selenium\edge117\msedge.exe'
# 浏览器实例
s = Service("selenium\msedgedriver117.exe")
driver = webdriver.Edge(service= s,options= option)
driver.get("https://xxxxx.yuketang.cn/web")
# 开始登陆
time.sleep(10)# 给时间扫码
# 找到课程
tab_student = driver.find_element(By.ID, 'tab-student')
tab_student.click()
time.sleep(1)
class_btn = driver.find_element(By.XPATH, f'//*[@id="pane-student"]//h1[contains(text(),{name})]')
class_btn.click()
time.sleep(1)
# 点击成绩单页面
grade = driver.find_element(By.XPATH, '//div[@id="tab-student_school_report"]/span')
grade.click()
time.sleep(1)
# 刷课
def study():
lessons = driver.find_elements(By.XPATH, '//li[@class="study-unit"]')
for lesson in lessons:
statistic = lesson.find_element(By.CSS_SELECTOR, 'div.complete-td span').text
if statistic == "已完成" or statistic == "已发言" or statistic == "未发言" or statistic == "未开始":
continue # 判断课程状态
else:
lesson_btn = lesson.find_element(By.CSS_SELECTOR, '.name-text')
driver.execute_script("$(arguments[0]).click()", lesson_btn)# 点击进入课程按钮
time.sleep(2)
driver.switch_to.window(driver.window_handles[-1])# 切换到课程窗口
#volume_btn = driver.find_element(By.XPATH, '//xt-icon')
#driver.execute_script("$(arguments[0]).click()", volume_btn)# 静音播放
finish_bar = driver.find_element(By.XPATH, '//span[@class="text"]').text
while finish_bar != "完成度:100%":
time.sleep(5)
finish_bar = driver.find_element(By.XPATH, '//span[@class="text"]').text# 每五秒刷新状态值
driver.close()
driver.switch_to.window(driver.window_handles[0])# 关闭刷课窗口并回到成绩单窗口
driver.refresh()# 刷新窗口获得课程完成状态
time.sleep(1)
grade = driver.find_element(By.XPATH, '//div[@id="tab-student_school_report"]/span')
grade.click()
time.sleep(1)# 点击转换到成绩单窗口
study()
study()
time.sleep(5)
|