11'''
22Author: LetMeFly
3- Date: 2021-11-01 15:52:32
3+ Date: 2023-09-12 20:49:21
44LastEditors: LetMeFly
5- LastEditTime: 2023-09-12 19:27:08
5+ LastEditTime: 2023-09-22 21:38:54
6+ Description: 开源于https://github.com/LetMeFly666/YuketangAutoPlayer 欢迎issue、PR
67'''
7-
88from selenium import webdriver
9+ from selenium .webdriver import ActionChains
10+ from selenium .webdriver .support .ui import WebDriverWait
911from time import sleep
10- driver = webdriver .Chrome ()
11-
12- # 访问雨课堂并点击“登录”按钮
13- driver .get ("https://grsbupt.yuketang.cn/" )
14- driver .find_element_by_class_name ("login-btn" ).click ()
15- print ("请扫码登陆" )
16-
17- # 判断是否已经登陆成功
18- while True :
19- location = driver .current_url
20- if "courselist" in location :
21- break
22- sleep (0.5 )
23- print ("登录成功" )
24-
25- # 完成一门课程的函数
26- def finishThisCourse (courseId ):
27- # 访问此视频
28- driver .get ("https://grsbupt.yuketang.cn/pro/lms/84eubUXLHEy/17556639/video/" + courseId )
29- # 判断是否已经完成
30- sleep (3 )
31- if len (driver .find_elements_by_class_name ("icon--gou" )):
32- print ("此课程已完成" )
33- return True
34- def ifCouldPlayAVideo ():
35- videoTag = driver .find_element_by_id ("video-box" )
36- return len (videoTag .find_elements_by_tag_name ("div" ))
37- couldPlayVideo = False
38- for tryTimes in range (5 ): # 尝试5次,一次可能是因为网络,5次大概率不是视频
39- if ifCouldPlayAVideo ():
40- couldPlayVideo = True
41- print ("是课程" )
42- break
43- sleep (2 )
44- if not couldPlayVideo :
45- print ("不是课程" )
46- return False # 认为不是视频
47- sleep (5 )
48- # video = driver.find_element_by_tag_name("video")
49- # def ifVideoPaused():
50- # result = driver.execute_script("return document.querySelector('video').paused;")
51- # return result
52- # tryToPlayTimes = 0
53- # while ifVideoPaused():
54- # print("暂停状态")
55- # try:
56- # playButton = driver.find_element_by_class_name('xt_video_player_play_btn')
57- # playButton.click()
58- # except:
59- # driver.execute_script("document.querySelector('.xt_video_player_play_btn').click();")
60- # driver.execute_script("console.log(document.querySelector('.xt_video_player_play_btn'));")
61- # driver.execute_script("document.querySelector('video').play();")
62- # tryToPlayTimes += 1
63- # if tryToPlayTimes > 7:
64- # driver.refresh()
65- # tryToPlayTimes = 0
66- # # while True:
67- # # try:
68- # # script = input("请输入要执行的脚本")
69- # # print(driver.execute_script(script))
70- # # except:
71- # # print("执行失败")
72- # sleep(3)
73- # sleep(1)
74-
75- driver .execute_script ("video = document.querySelector('video');" )
76- element_video = driver .find_element_by_tag_name ('video' )
77- webdriver .ActionChains (driver ).move_to_element (element_video ).perform ()
78- webdriver .ActionChains (driver ).click ().perform ()
79- driver .execute_script ("startVideo = setInterval(() => {video.play(); console.log('尝试播放视频');}, 1000); setTimeout(() => {clearInterval(startVideo); console.log('停止尝试播放视频')}, 5200);" )
80- print ("正在播放" )
81- driver .execute_script ("video.addEventListener('pause', function() {video.play();});" )
82- sleep (5 )
83- element_speeds = driver .find_element_by_class_name ('xt_video_player_common_value' )
84- webdriver .ActionChains (driver ).move_to_element (element_speeds ).perform ()
85- sleep (0.2 )
86- element_speed2 = driver .find_element_by_xpath ('//*[@id="video-box"]/div/xt-wrap/xt-controls/xt-inner/xt-speedbutton/xt-speedlist/ul/li[1]' )
87- webdriver .ActionChains (driver ).move_to_element_with_offset (element_speed2 , 3 , 5 ).perform ()
88- sleep (0.3 )
89- element_speed2 .click ()
90- # webdriver.ActionChains(driver).context_click(element_speed2).perform()
91-
92- while not len (driver .find_elements_by_class_name ("icon--gou" )):
93- sleep (1 )
94- print ("此课程播放完毕!" )
95- return True
96-
97-
98- # 访问每一门课
99- for courseId in range (37551787 , 37551907 + 1 ):
100- # try:
101- if True :
102- finishThisCourse (str (courseId ))
103- # except:
104- # pass
105- print ("全部完成!" )
106-
107-
108-
109- # 雨课堂字幕:https://buct.yuketang.cn/mooc-api/v1/lms/service/subtitle_parse/?c_d=0D0C4F3DE7D58B649C33DC5901307461&lg=0&_=1665473764724
12+ import random
13+
14+
15+ IF_HEADLESS = False # 是否以无窗口模式运行(首次运行建议使用有窗口模式以观察是否符合预期)
16+ COURSE_URL = 'https://grsbupt.yuketang.cn/pro/lms/84eubUXLHEy/17556639/studycontent' # 要刷的课的地址(获取方式见README)
17+ COOKIE = 'sjfeij2983uyfh84y7498uf98ys8f8u9' # 打死也不要告诉别人哦(获取方式见README)
18+
19+
20+ option = webdriver .ChromeOptions ()
21+
22+ if IF_HEADLESS :
23+ option .add_argument ('--headless' )
24+
25+ driver = webdriver .Chrome (options = option )
26+ driver .maximize_window ()
27+ driver .implicitly_wait (20 )
28+
29+ def str2dic (s ):
30+ d = dict ()
31+ for i in s .split ('; ' ):
32+ temp = i .split ('=' )
33+ d [temp [0 ]] = temp [1 ]
34+ return d
35+
36+
37+ def setCookie (cookies ):
38+ driver .delete_all_cookies ()
39+ for name , value in cookies .items ():
40+ driver .add_cookie ({'name' : name , 'value' : value , 'path' : '/' })
41+
42+
43+ def ifVideo (div ):
44+ i = div .find_element_by_tag_name ('i' )
45+ i_class = i .get_attribute ('class' )
46+ return 'icon--shipin' in i_class
47+
48+
49+ def getAllvideos_notFinished (allClasses ):
50+ allVideos = []
51+ for thisClass in allClasses :
52+ if ifVideo (thisClass ) and '已完成' not in thisClass .text :
53+ allVideos .append (thisClass )
54+ return allVideos
55+
56+
57+ def get1video_notFinished (allClasses ):
58+ for thisClass in allClasses :
59+ if ifVideo (thisClass ) and '已完成' not in thisClass .text :
60+ return thisClass
61+ return None
62+
63+
64+ # driver.get('https://grsbupt.yuketang.cn/')
65+ driver .get ('https://' + COURSE_URL .split ('https://' )[1 ].split ('/' )[0 ] + '/' )
66+ cookies = {'sessionid' : COOKIE }
67+ setCookie (cookies )
68+ driver .get (COURSE_URL )
69+
70+
71+ def change2speed2 ():
72+ speedbutton = driver .find_element_by_tag_name ('xt-speedbutton' )
73+ ActionChains (driver ).move_to_element (speedbutton ).perform ()
74+ ul = speedbutton .find_element_by_tag_name ('ul' )
75+ lis = ul .find_elements_by_tag_name ('li' )
76+ li_speed2 = lis [0 ]
77+ diffY = speedbutton .location ['y' ] - li_speed2 .location ['y' ]
78+ # ActionChains(driver).move_to_element_with_offset(speedbutton, 3, 5).perform()
79+ # ActionChains(driver).click().perform()
80+ # 我也不知道为啥要一点一点移动上去,反正直接移动上去的话,点击是无效的
81+ for i in range (diffY // 10 ): # 可能不是一个好算法
82+ ActionChains (driver ).move_by_offset (0 , - 10 ).perform ()
83+ sleep (0.5 )
84+ sleep (0.8 )
85+ ActionChains (driver ).click ().perform ()
86+
87+
88+ def mute1video ():
89+ if driver .execute_script ('return video.muted;' ):
90+ return
91+ voice = driver .find_element_by_tag_name ('xt-volumebutton' )
92+ ActionChains (driver ).move_to_element (voice ).perform ()
93+ ActionChains (driver ).click ().perform ()
94+
95+
96+ def finish1video ():
97+ allClasses = driver .find_elements_by_class_name ('leaf-detail' )
98+ allVideos = getAllvideos_notFinished (allClasses )
99+ if not allVideos :
100+ return False
101+ video = allVideos [0 ]
102+ driver .execute_script ('arguments[0].scrollIntoView(false);' , video )
103+ video .click ()
104+
105+ driver .switch_to .window (driver .window_handles [- 1 ])
106+ WebDriverWait (driver , 10 ).until (lambda x : driver .execute_script ('video = document.querySelector("video"); console.log(video); return video;' )) # 这里即使2次sleep3s选中的video还是null
107+ driver .execute_script ('videoPlay = setInterval(function() {if (video.paused) {video.play();}}, 200);' )
108+ driver .execute_script ('setTimeout(() => clearInterval(videoPlay), 5000)' )
109+ driver .execute_script ('addFinishMark = function() {finished = document.createElement("span"); finished.setAttribute("id", "LetMeFly_Finished"); document.body.appendChild(finished); console.log("Finished");}' )
110+ driver .execute_script ('lastDuration = 0; setInterval(() => {nowDuration = video.currentTime; if (nowDuration < lastDuration) {addFinishMark()}; lastDuration = nowDuration}, 200)' )
111+ driver .execute_script ('video.addEventListener("pause", () => {video.play()})' )
112+ mute1video ()
113+ change2speed2 ()
114+ while True :
115+ if driver .execute_script ('return document.querySelector("#LetMeFly_Finished");' ):
116+ print ('finished, wait 5s' )
117+ sleep (5 ) # 再让它播5秒
118+ driver .close ()
119+ driver .switch_to .window (driver .window_handles [- 1 ])
120+ return True
121+ else :
122+ print (f'not finished { random .random ()} ' )
123+ sleep (3 )
124+ return False
125+
126+
127+ while finish1video ():
128+ driver .refresh ()
129+ driver .quit ()
130+ print ('恭喜你!全部播放完毕' )
131+ sleep (5 )
0 commit comments