preface
You need to hang a video in a learning class. There is no interference during the video playback of the website, so as long as all the video clips under the course can go from beginning to end.
- The same hanging video py script has been done before, which is implemented by python+selenium. So I wanted to implement it in the same way at first. This is the first method. Disadvantages: python and selenium webdriver are required. At present, I really can't think of the advantages of the other two methods.
- Because the video playback action and clicking on the next clip use selenium's webdriver execute_ The script () function sends the js code to the browser for implementation, which is to add some js code to the page. Suddenly think of such an implementation, isn't it over to use the oil monkey script? python and webdriver are not needed yet. As long as the video page is opened on the browser with oil monkey installed, the automatic playback function can be added. This is the second method. Disadvantages: you need a browser that can install the oil Monkey (Firefox / Chroom / edge), install the oil monkey extension, and add a script in the oil monkey. It is really not friendly to the computer Xiaobai. Advantages: the function can be realized directly in the browser, and the video page will work automatically without any other operation.
- Inspired by the third way of using reable's Sent to Kindle, make the js code into a bookmark button, and then enter the video page and click the bookmark button. Disadvantages: you need to know how to set the bookmark button and set "show favorites bar" in the browser. As long as you click a bookmark in the browser, you can automatically call it as a bookmark in advance, and then you can use a different bookmark function in the browser.
Of the three methods, I prefer the third one. Because as long as you write down the js code, no matter where you are and what browser you use, it can be used without installing other software or extensions.
The first method: phthon+selenium
V0. Version 1 realizes the basic functions, and then v0 Version 2 does object-oriented reconstruction. Because I thought of a more convenient implementation method, I didn't continue to optimize the code carefully.
# Automatic video playback in general service cloud classroom # V0.2: Functional reconstruction import time from selenium import webdriver from selenium.common.exceptions import NoSuchElementException LOGIN_URL = 'https://www.ccspx.com.cn/login' USER = '*******' PWD = '*******' driver = webdriver.Edge(executable_path='msedgedriver.exe') class Player: def __init__(self, parallel_num, proceed, task_center_title='Task Center'): self.parallel_num = parallel_num self.proceed = proceed self.task_center_title = task_center_title self.tasks = [] self.logined = False def run(self): self._login() self._create_tasks() for task in self.tasks: task.start() time.sleep(3) for task in self.tasks: print(f'{task.name}\n{task.command}\n{task.video_fragment_commands}\n----------------------') while self.tasks: time.sleep(10) for i in range(len(self.tasks)): self.tasks[i].check_video_ended() if self.tasks[i].completed: self.tasks.remove(self.tasks[i]) def _login(self): driver.get(LOGIN_URL) time.sleep(1) driver.find_element_by_id('username').send_keys(USER) driver.find_element_by_id('password').send_keys(PWD) driver.find_element_by_id('validateCode').click() while True: try: driver.find_element_by_id('username') except NoSuchElementException: self.logined = True break time.sleep(2) def _create_tasks(self): window = None while window is None: time.sleep(10) for w in driver.window_handles: driver.switch_to.window(w) if driver.title == self.task_center_title: window = w driver.switch_to.window(window) time.sleep(2) task_commands = [a.get_attribute('onclick') for a in driver.find_elements_by_xpath('//div[@id="dataList"]//li/a')] progresses = [span.text for span in driver.find_elements_by_xpath('//div[@id="dataList"]//li//span')] for c, p in zip(task_commands, progresses): if self.proceed: if p != '100%': self.tasks.append(Task(command=c, parent_window=window, proceed=self.proceed)) else: self.tasks.append(Task(command=c, parent_window=window, proceed=self.proceed)) class Task: def __init__(self, command, parent_window, proceed): self.command = command self.parent_window = parent_window self.proceed = proceed self.running = False self.completed = False self.name, self.window = None, None self.video_fragment_commands = [] def start(self): driver.switch_to.window(self.parent_window) driver.execute_script(self.command) time.sleep(3) self.window = driver.window_handles[-1] driver.switch_to.window(self.window) self.name = driver.title self._get_video_fragments() self._play() def _get_video_fragments(self): driver.switch_to.window(self.window) fragment_commands = [li.get_attribute('onclick') for li in driver.find_elements_by_xpath('//li[contains(@class, "task-item")]')] progresses = [sp.text for sp in driver.find_elements_by_xpath('//li[contains(@class, "task-item")]//span')][ 2::3] for c, p in zip(fragment_commands, progresses): if self.proceed: if p != '100%': self.video_fragment_commands.append(c) else: self.video_fragment_commands.append(c) def _play(self): if len(self.video_fragment_commands) != 0: driver.switch_to.window(self.window) driver.execute_script(self.video_fragment_commands[0]) time.sleep(2) driver.execute_script('document.getElementsByTagName("video")[0].play();') else: self.completed = True driver.execute_script('alert("There is no video or acquisition error on the page");') def check_video_ended(self): driver.switch_to.window(self.window) if driver.find_element_by_tag_name('video').get_property('ended'): self.video_fragment_commands.pop(0) if len(self.video_fragment_commands) == 0: self.completed = True driver.execute_script('alert("Video playback completed");') # driver.close() else: self._play() else: driver.execute_script('document.getElementsByTagName("video")[0].play();') def __repr__(self): return f'{self.__class__.__name__}(name={self.name}, command={self.command}, ' \ f'video_fragments={self.video_fragment_commands})' def main(): player = Player(parallel_num=5, proceed=False) player.run() if __name__ == '__main__': main()
The second method: use oil monkey expansion
Idea: add a timing caller setInterval. The player checks whether the video is played every 4.4 seconds and whether the next clip is played.
// ==UserScript== // @name General Service cloud classroom - auto play / mute // @namespace * // @version 0.1 // @description automatically play the video of "general service cloud classroom" // @author czbuyi // @match https://www.ccspx.com.cn/course/detail* // @grant none // ==/UserScript== (function() { if(confirm("Start video autoplay?")){ setInterval(function(){ let player = document.getElementsByTagName('video')[0]; if(player.ended){ let all = [].slice.call(document.getElementsByClassName('task-item')); let active = document.getElementsByClassName('task-item active')[0]; let next_index = all.indexOf(active)+1; console.log(all.indexOf(active)); if (next_index <= all.length-1){ all[next_index].click(); }else{ alert("End of video playback"); window.close(); } }; player.play(); player.muted=true; }, 4000) } // Your code here... })();
The third method: use the label button
js code is the same as the second method. In order to make tags, add "javascript:" in front of js code, remove carriage return and put them in one line.
javascript:(function(){if(confirm("Start video autoplay?")){setInterval(function(){let player=document.getElementsByTagName('video')[0];if(player.ended){let all=[].slice.call(document.getElementsByClassName('task-item'));let active=document.getElementsByClassName('task-item active')[0];let next_index=all.indexOf(active)+1;if(next_index<=all.length-1){all[next_index].click();}else{alert("End of video playback");window.close();}};player.play();player.muted=true;},4000)}})();
Record several pits
- Before I find and operate an element or test js code in the web page, I always use the running code (through python, html, js script) to detect. Each time, it may involve login, clicking to the target page, refreshing, etc., which wastes a lot of time and energy. Later, it was found that you can directly enter the test under the console of the browser "developer debugging tool" (press F12 to call it out), and you will see the results immediately, which is very direct and convenient.
- The video element in the video playback page of this website will change, so you need to get the video element again every time. Due to the same problem, the end event cannot be added to the video element to handle the operation after the video clip is played.
- To achieve continuous playback, you need to find the il element of the next clip. However, there are some differences in the structure of each page, so we have to find out all the il with "task item" class in the page and turn it into an array, then find the il element of "task item active" class, and determine the il of the next segment by checking its position in the array.
- js document Getelementsby * * * returns an HTMLCollection object, which is similar to an array and can be traversed by for, but there is no indexOf function, so the position of an element in the object cannot be determined. Because in the implementation of playing the next clip, I need to find the il of the current "task item active" class and click the next il element, so I can only convert the HTMLCollection object into an array: all = [] slice. Call (document.getelementsbyclassname ('task item '))
- The attributes defined in < > of html elements can be obtained by using getattribute ("attribute name"), such as video element getAttribute(“scr”) . However, for the status of video element, such as "ended" at the end of playback, muted, etc., the video element is directly used End to judge.