前言:
遇到一個視頻學習平臺,視頻無法快進,學習過程中會出現習題,需要在一定時間內提交答案(不管對錯),纔會繼續視頻的學習。其間若是逾時不答題或是出現其它錯誤,視頻播放進度都不算。
使用Python + selenium,實現自動掛視頻:
- 半自動登錄。帳號密碼可設定,在登錄頁面會自動輸入,但需要自己輸入驗證碼(這一塊處理起來也不難,它的驗證碼還是比較好辯認),並且點擊“個人登錄”。
- 自動進入課程學習。
- 處理在視頻播放時間裏出現的所有情況:答題、錯誤提示等。
- 播放完畢後自動進入下一個課程。
- 全程使用一個logger裝飾器,把main()包裝起來,讓所有的輸出(包括錯誤)轉存到logger.log文件中。
- 最主要是在handle_interference()函數中,處理播放視頻時出現的所有干擾,以便視頻能順利播放完。
代碼如下 :
# -*- coding: utf-8 -*-
"""
廣東省******公需課在線學習平臺 自動點播
存在問題:handle_interference()中處理“網絡故障”的判斷條件不正確
"""
import time
import sys
import functools
from selenium import webdriver
from selenium.common import exceptions
USER_NAME = '******'
USER_PWD = '******'
now = time.strftime('[%H:%M:%S]', time.localtime())
login_url = 'http://******/zxpx/index?f=73075572383248020' # 登錄頁面
classes_url = 'http://******/zxpx/hyper/courseDetail?ocid=OC201903290000005403' # “課程詳情”頁面地址
def logger(func):
""" 裝飾器 將系統輸出轉到logger.log文件 """
@functools.wraps(func)
def log():
with open('logger.log', 'a', encoding='utf-8') as log_file:
org_err, org_out = sys.stderr, sys.stdout
sys.stderr, sys.stdout = log_file, log_file
func()
sys.stderr, sys.stdout = org_err, org_out
return log
def login(driver, url):
""" 登錄平臺 """
try:
driver.get(url)
time.sleep(2)
driver.find_element_by_id('username_personal').send_keys(USER_NAME)
driver.find_element_by_id('password_personal').send_keys(USER_PWD)
driver.find_element_by_id('vcode_personal').click()
# 手動填寫驗證碼,並登錄
while True:
time.sleep(3)
if driver.title == '首頁':
return True, None
except exceptions.NoSuchElementException:
return False, '非登錄頁面'
def start_new_video(driver, n):
""" 獲取並開始新課視頻 """
try:
new_class = driver.find_elements_by_xpath('//a[contains(text(), "點擊學習")]')[n]
except:
return False, '找不到學習課程。'
else:
print('{} 開始新一課: {}'.format(now, new_class.get_attribute('href')))
new_class.click()
time.sleep(5)
state, msg = play_video(driver)
if state:
return True, 'success'
else:
return False, msg
def play_video(driver):
""" 點擊頁面中的視頻object元素,開始播放 """
if driver.title == '課件學習':
try:
driver.find_element_by_xpath('//object/embed').click()
except exceptions.NoSuchElementException:
return False, '找不到視頻'
else:
return True, 'success'
else:
return False, '非課件網面'
def handle_interference(driver):
"""
自動點擊處理視頻播放過程中出現的題目選擇和異常告警
:return:
(True, 'next_class"): 正常,並視頻播放完畢
(Flase, msg):異常
"""
print('{} 處理視頻頁面:答題和錯誤處理'.format(now))
while driver.title == '課件學習':
# 處理頁面中出現的異常對話框:選擇確定
try:
driver.find_element_by_xpath('//*[contains(text(), "確定")]').click()
print('{} 選擇確定'.format(now))
time.sleep(1)
except:
pass
# 選擇視頻過程中出現題目的正確答案
try:
driver.find_element_by_xpath('//div[@id="aadiv"]/input').click()
print('{} 選擇正確'.format(now))
time.sleep(1)
except:
pass
# 提交答案
try:
driver.find_element_by_class_name('reply-sub').click()
print('{} 選擇提交'.format(now))
time.sleep(1)
except:
pass
# 若出現告警對話框時選擇確定通過
try:
driver.switch_to.alert.accept()
print('{} 對話框確定'.format(now))
time.sleep(1)
except:
pass
# 視頻播放的進度(正常情況下以**%的形式出現,異常則說明視頻播放完畢)
try:
driver.find_element_by_id('realPlayVideoTime')
except exceptions.NoSuchElementException:
return True, 'next_class'
# 處理網絡故障提示
try:
driver.find_element_by_xpath('//*[contains(text(), ‘網絡故障,請刷新’)]') # 網絡故障這個提示有點問題,待修復
driver.find_element_by_xpath('//*[contains(text(), "確定")]').click()
except:
pass
else:
driver.refresh()
print('{} 刷新頁面'.format(now))
time.sleep(3)
state, msg = play_video(driver)
if not state:
return False, msg
time.sleep(5)
@logger
def main():
with webdriver.Ie(executable_path='IEDriverServer.exe') as driver:
logined, login_msg = login(driver, login_url)
if logined:
while True:
driver.get(classes_url)
time.sleep(2)
new_video_state, new_video_msg = start_new_video(driver, 0)
if new_video_state:
handle_state, handle_msg = handle_interference(driver)
if not handle_state:
print('{} {}'.format(now, handle_msg))
else:
print('{} {}'.format(now, new_video_msg))
return False
else:
print('{} {}'.format(now, login_msg))
return False
if __name__ == '__main__':
main()