一、简介
仅供学习讨论,请勿用于刷课!
本文主要介绍使用Python3+Selenium+Chromedriver来实现一个自动刷网课的小脚本,目标网课平台是智慧树。
二、环境配置
笔者的平台是Win10,其它平台未做尝试。需要配置以下环境:
- pip install selenium
- 下载ChromeDriver(注意下载与自己的Chrome浏览器相对应的版本),并将ChromeDriver.exe放置在Chrome.exe相同目录下,并将该路径添加至环境变量中。(如笔者的路径是C:\Program Files (x86)\Google\Chrome\Application)
三、Selenium与ChromeDriver简单介绍
- Selenium 是一个用于Web应用程序自动化测试的工具,它直接运行在浏览器中,就像真正的用户在操作一样。
- Selenium支持众多浏览器,其中就包括Chrome,搭配ChromeDriver对Chrome进行驱动即可模拟用户操纵Chrome进行操作。
- Selenium支持许多语言,比如python直接通过pip install selenium即可下载selenium包
四、Show me the code
Selenium的教程网上已有许多,读者可以自行搜索。下面直接上代码,代码仅一百行,用到的也都是基本操作,仅供读者参考,运行中可能由于网络延迟等各种情况抛出异常,读者可自行做相应修改。附上github链接
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, NoSuchElementException, ElementClickInterceptedException
import time
from selenium.webdriver.common.action_chains import ActionChains
debug = True
def log(text):
if debug:
print(text)
else:
pass
if __name__ == '__main__':
url = 'https://passport.zhihuishu.com/login?service=https://onlineservice.zhihuishu.com/login/gologin'
course = "" #课程名称
university = "" #学校名称
student_code = "" #学号
passport = "" #密码
count = 2 #要看的集数
browser = webdriver.Chrome()
wait = WebDriverWait(browser, 10)
browser.get(url)
#添加cookie减少弹窗数量
browser.add_cookie({'name' : 'cookieServer', 'value' : '1', 'domain' : '.zhihuishu.com'})
browser.add_cookie({'name' : 'warningTip', 'value' : '1', 'domain' : '.zhihuishu.com'})
#登录操作
log('开始登录')
wait.until(EC.element_to_be_clickable((By.LINK_TEXT, '学号'))).click()
wait.until(EC.presence_of_element_located((By.ID, 'quickSearch'))).send_keys(university)
wait.until(EC.presence_of_element_located((By.ID, 'clCode'))).send_keys(student_code)
wait.until(EC.presence_of_element_located((By.ID, 'clPassword'))).send_keys(passport)
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#schoolListCode > li > b > font'))).click()
wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'wall-sub-btn'))).click()
#进入对应课程
log('进入课程')
wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'courseName')))
course_list = browser.find_elements_by_class_name('courseName')
flag = -1
for index,item in enumerate(course_list):
if item.text == course:
flag = index
break
if flag != -1:
course_list[index].click()
else:
log("未找到对应课程")
exit()
#关闭成绩提醒(可能会被弹题窗口挡住,要处理这种情况)
try:
wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'popboxes_close'))).click()
except ElementClickInterceptedException:
pop_chapter = browser.find_element_by_class_name('tanti_popchapter')
ActionChains(browser).move_to_element(pop_chapter).click().perform()
browser.find_element_by_link_text('关闭').click()
wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'popboxes_close'))).click()
new_episode = True
while count > 0:
time.sleep(5)
#模拟鼠标划入播放窗口的操作,唤起底部控制栏
video_area = wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'videoArea')))
#识别当前状态(播放、暂停、播放完、问题弹出)
try:
playButton = browser.find_element_by_class_name('playButton')
except NoSuchElementException:
if new_episode:
#调至1.5倍速
ActionChains(browser).move_to_element(video_area).perform()
wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'speedBox'))).click()
wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'speedTab15'))).click()
log('设置1.5倍速')
#调静音
wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'volumeBox'))).click()
log('设置静音')
#设置标志位
new_episode=False
else:
#判断是否有弹窗弹出或是播放完
try:
pop_chapter = browser.find_element_by_class_name('tanti_popchapter')
except NoSuchElementException:
pass_time = browser.find_element_by_class_name('passTime')
ActionChains(browser).move_to_element(video_area).perform()
if pass_time.get_attribute('style') == 'width: 100%;':
count = count - 1
if count != 0:
wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'nextButton'))).click()
new_episode=True
log('播放下一集')
else:
log('继续播放')
playButton.click()
else:
ActionChains(browser).move_to_element(pop_chapter).click().perform()
browser.find_element_by_link_text('关闭').click()
log('关闭弹窗')
print('已经看完目标集数,程序退出')