前言
学校在智慧树平台安排有课程,我不想学但不得不学,就这么简单。(这种大逆不道的话你也敢说的吗兄嘚)。
啊哈哈哈,那当然不是了。我是热爱学习,渴望用知识的力量武装自己的当代油锈大学生,学校为我们提供了如此精良的课程,我们当然不能辜负学校的良苦用心才是啊。
可是!可是!某人听课有个习惯,一定是全神贯注仔细听讲。因为哪怕只有一点点外界干扰,都会影响整体的心流状态,如果因为这个原因,影响了学习掌握新知识的效率,那真的会痛心不已(脸皮是真的厚)。
请诸位试想,你正津津有味地聆听网课老师的绝妙理论,沉浸其中无法自拔时,突然,跳出来一个弹窗暂停了视频播放,中断了你的听课状态,要求你答题,答完题才能接着看,你说说,这不是欺负老实人吗。我就想安安静静听课,课后练习题,你等我听完课再让去做不好么。真的是,猴猴急。
还有还有,你看完一节网课,掌握了更多新知识的同时,心中多多少少也有更多的疑惑,迫切想听接下来的课程,从中获取到你想要的答案。可惜智慧树它偏不,它在播放完一节网课之后竟然不能自动播放下一个视频。连这样简单的自动连播都不给实现,这我不能忍了。既然如此,那就由我来“调教”一下。
那需求就是:首先,应该“跳过”视频播放过程中出现的问题小弹窗,然后,实现视频自动连播功能。
直接安排!
实现
#导入需要的库
from selenium import webdriver #selenium库,核心库,webdriver对象用来操作浏览器
from selenium.webdriver.common.by import By #用于定位页面元素
from selenium.webdriver.common.action_chains import ActionChains #处理鼠标事件(如鼠标悬停等)
from time import sleep #time标准库,用于程序休眠
设定一些启动参数,比如关闭Selenium的控制台日志,让控制台清爽一点。
options = webdriver.EdgeOptions()
options.add_experimental_option('excludeSwitches', ['enable-logging']) #关闭selenium日志输出
options.add_argument("--mute-audio") #浏览器静音
Edge = webdriver.Edge(options=options) #创建webdriver对象
Edge.implicitly_wait(10) #设定全局等待时间,10秒
接下来,用代码打开智慧树官网主页,检查【登录】的元素,很棒啊!智慧树很给面子地用一个id标识了登录按钮。那我们要实现模拟点击【登录】,只需要用这个id在Selenium中定位就好了。
写个死循环,让程序一直检测视频播放页面的元素。如果检测到并能成功点击,说明用户已经顺利进入了视频播放界面。为什么要用死循环呢?因为当我们模拟点击登录之后,智慧树跳转进入用户登录页面等待用户登录。而用户什么时候登录完成,并进入视频播放界面,我们是不能确定的。但是后续代码必须保证当前页面在视频播放页面才能继续执行,所以写一个死循环,当条件满足时用break退出去,正常执行后续代码。什么?你问我如果用户迟迟不等登录,或者用户操作不当,没有进入视频播放界面怎么办?怎么办,简单啊,让它一直死循环就好了,直到用户进入了正确的页面,这样可以规避了因用户操作问题导致的程序崩溃。
直到用户进入视频播放页面,我们在视频播放页面找个元素,这个元素要保证,一旦循环找到了这个元素,就确实能证明我进入了这个页面,可以退出循环执行后续代码。我找的元素是这个。
智慧树还是很温柔地,用一个class标识了这个元素,我们还是可以很轻易地定位到它。代码如下。
Edge.get("http://www.zhihuishu.com/") #打开知到智慧树官网
Edge.find_element(By.ID,"notLogin").click() #定位到【登录】
while True: #等待用户登录、进入课程
try:
Edge.find_element(By.CLASS_NAME,"hint_delete").click()
except:
print("未找到课程")
else:
break
okk,到了这里,万事俱备,可以着手实现功能了。首先。要实现自动播放下一个视频,需要知道当前课程总共有多少视频、现在已经看完的视频有几个。
通过查找页面元素我们发现,智慧树将每一个视频统一用一个class标识,所以我们只需要用.find_elements()方法,这个方法返回一个列表,能获取到所有指定特征的元素,那么这个列表的长度,就是课程数量。同理,智慧树将以看完的课程后面标识了一个小图标,我们只需要获取到这个小图标的个数,就能得到已经看完的课程数量。
代码如下:
icofinishlist = Edge.find_elements(By.CLASS_NAME,"fl.time_icofinish") #存放已完成的课程,列表
Allvideolist = Edge.find_elements(By.CLASS_NAME,"clearfix.video") #存放全部课程,列表
Allvideolist[len(icofinishlist)].click() #进入未完成的第一个课程
说到这里,我想应该能够体会selenium定位元素的方法了吧。后面的代码部分原理还是一样的,找元素,点击元素就好了,元素的特征定位也很简单,基本上全是通过class就能定位。直接贴代码:
sleep(5)
videoArea = Edge.find_element(By.CLASS_NAME,"videoArea") #视频播放区域
ActionChains(Edge).move_to_element(videoArea).perform() #鼠标悬停
speedBox = Edge.find_element(By.CLASS_NAME,"speedBox") #视频倍速按钮
ActionChains(Edge).move_to_element(speedBox).perform() #鼠标悬停
Edge.find_element(By.CLASS_NAME,"speedTab.speedTab15").click() #视频1.5倍速
definiBox = Edge.find_element(By.CLASS_NAME,"definiBox") #视频清晰度按钮
ActionChains(Edge).move_to_element(definiBox).perform() #鼠标悬停
Edge.find_element(By.CLASS_NAME,"line1bq.switchLine").click() #视频【流畅】清晰度
Edge.find_element(By.ID,"playButton").click() #视频播放按钮
while True: #循环,检测小弹窗
try:
Edge.find_elements(By.CLASS_NAME,"topic-item")[0].click() #小弹窗选项,默认选第一个(A)
except:
print("未检测到小测验弹窗")
else:
print("检测到小测验弹窗")
btn1 = Edge.find_element(By.CLASS_NAME,"el-dialog__wrapper.dialog-test")
btn2 = btn1.find_element(By.CLASS_NAME,"el-dialog")
btn3 = btn2.find_element(By.CLASS_NAME,"el-dialog__headerbtn").click()
sleep(3)
videoArea = Edge.find_element(By.CLASS_NAME,"videoArea") #视频播放区域
ActionChains(Edge).move_to_element(videoArea).perform() #鼠标悬停
Edge.find_element(By.ID,"playButton").click() #重新播放视频
break
关于代码中鼠标悬停那部分,是因为智慧树的视频播放界面,播放、调整倍速、调整清晰度等等这些控件,是要用户先将鼠标悬停到视频播放区域才会可见的。于是我们用Selenium提供的ActionChains类模拟鼠标操作,实现悬停。然后是死循环,不停检查视频内小弹窗元素。当弹窗出现时,随便点击一个问题的答案,关闭小弹窗就可以了。这样第一个功能:“跳过”视频内小弹窗,就这样实现了。
接下来用一个大循环,不断检查现在已经看完的视频列表(也就是能代表视频已经看完的那个小图标)有没有新增。如果有新增,说明当前视频已经播放完毕了,可以进入下一个视频了。这样就实现了自动连播,代码如下:
while True:
Nowicofinish = Edge.find_elements(By.CLASS_NAME,"fl.time_icofinish")
if len(Nowicofinish) == len(icofinishlist)+1:
icofinishlist = Edge.find_elements(By.CLASS_NAME,"fl.time_icofinish") #更新已完成的课程,列表
Allvideolist[len(icofinishlist)].click() #进入下一个未完成的课程
print("进入下一课")
后记
我对selenium的理解就是,定位元素,然后操作元素。定位元素很简单,在网页页面用开发者工具检查元素,然后根据元素的一系列相关特征,在代码中用selenium提供的方法,定位到你指定的元素,操作它就好了。但是说者简单,真正实操起来,还是有各种问题和难度的。好在智慧树这个网页比较“温柔”,没有设定什么让人麻烦的东西,新手在掌握selenium基本语法之后,也大可以用这个平台练练手。(智慧树:你礼貌吗)。
实现方法其实很粗糙,而且局限性很大。但是无所谓啦,只是想通过它练练手。
感谢你能看到这里!
版权归原作者 下雪就该搓雪球 所有, 如有侵权,请联系我们删除。