selenium简单实现刷课

项目地址

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)