基于Selenium+Python的智慧树自动刷课

发布于 2023-02-03  1469 次阅读


前言

任选课居然还有平时分要求,真的难蚌

不会真有啥b期末考试满分结果平时分就一分然后挂科吧😎👌😭

学校你没有心😡

于是这个程序应运而生

查看更新请前往

https://github.com/AnyMoonS/AutoFinishLessons

正文

众所周知,智慧树是有脚本检测的,所以采取selenium这种模拟用户点击的方式相对来说要安全许多

导入所需包

from selenium import webdriver
from selenium.webdriver.common.by import By 
from selenium.webdriver.common.action_chains import ActionChains
import time
import threading # 开辟多线程用

打开智慧树的登录界面,进行一个自动登录(实际上这一步完全可以自动打开页面后手动登录,因为就算是自动登录你仍然要手动过滑动验证)

driver = webdriver.Firefox()
actions = ActionChains(driver)
driver.get("https://onlineweb.zhihuishu.com/")  # 打开智慧树官网
driver.maximize_window()
time.sleep(5)


def login():
    phonenumber = driver.find_element(By.ID, "lUsername")
    pw = driver.find_element(By.ID, "lPassword")
    loginbutton = driver.find_element(By.CLASS_NAME, "wall-sub-btn")
    phonenumber.send_keys(config.userid) # 账号
    pw.send_keys(config.password) # 密码
    loginbutton.click()

检测是否打开课程,并且设置1.5倍速(直接调网页可以达到很高的倍数播放,不过因为怕被检测,我也没试过😰)

def lesson():
    while 1:
        if driver.current_url.__contains__("studyvideoh5"):  # 检测打开视频播放页
            time.sleep(10)  # 等待手动关闭弹窗
            video = driver.find_element(By.CLASS_NAME, "videoArea")  # 定位视频窗口
            video.click()#播放视频
            try:
                ActionChains(driver).move_to_element(video).perform()
                speedbox = driver.find_element(By.CLASS_NAME, "speedBox")
                speedbox.click()
                time.sleep(1)
                speedtab15 = driver.find_element(By.CLASS_NAME, "speedTab15")  # 1.5倍播放
                speedtab15.click()
                break
            except:
                pass

在视频播放过程中,难免会有弹题验证,不过所幸智慧树比较仁慈,答题不需要正确就可以过关,所以我们直接定位A选项,不管啥题都选A就完事了

def test():
    while 1:
        try:
            question = driver.find_element(By.CLASS_NAME, "topic-item")  # 找到第一个选项
            question.click()
            time.sleep(1)
            close = driver.find_element(By.XPATH, "/html/body/div[1]/div/div[6]/div/div[3]/span/div")  # 关闭答题界面
            close.click()
            video = driver.find_element(By.CLASS_NAME, "videoArea")  # 定位窗口
            video.click()
        except:
            pass
        time.sleep(10)

最后是一个难点,获取视频播放的进度,检测是否播放完,我选择了一种比较笨的方案,直接读取进度条的当前时间与视频时长,相等之后单击下一个视频

这里有一个坑,使用get_attribute获取元素内的文本时,网上的教程大多都是使用textcontent,但是我实测之后发现textcontent会返回None,于是我采用了innerText,成功获取文本

def videoend():
    while 1:
        video = driver.find_element(By.CLASS_NAME, "videoArea")  # 定位窗口
        try:
            ActionChains(driver).move_to_element(video).perform()
            current_time = driver.find_element(By.CLASS_NAME, "currentTime")  # 当前视频播放时间
            total_time = driver.find_element(By.CLASS_NAME, "duration")  # 总时间
            time1 = current_time.get_attribute('innerText')
            time2 = total_time.get_attribute('innerText')
            if time1 == time2:
                video.click()
                nextvideo = driver.find_element(By.CLASS_NAME, "nextButton") #定位下一个视频按钮
                nextvideo.click()#切换到下一个视频
                lesson()
        except:
            pass
        time.sleep(10)

因为答题和视频播放是否结束都是要循环判定的,所以需要开设多线程

login()
lesson()
t1 = threading.Thread(target=test)
t2 = threading.Thread(target=videoend)
t2.start()
t1.start()

完工😋