前言:
遇到一个视频学习平台,视频无法快进,学习过程中会出现习题,需要在一定时间内提交答案(不管对错),才会继续视频的学习。其间若是逾时不答题或是出现其它错误,视频播放进度都不算。
使用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()