使用selenium自动化播课

警告:使用脚本刷课是不对的,好孩子不要这样做。

正好前些日子课上让学网络爬虫,就了解到了selenium————一个能实现网页自动化的库,Java、Py都能使。正好想到学习通上那无聊的网络选修课还不少没看,就准备来实操一下练练手。

我之前没发现java也行,就去py里搞了,还专门下了个PyCharm(JB家的东西真不错)。我这里配置库靠IDE,打完“import selenium”后就提示我自动安装了,浏览器引擎使得是Edge,去官网下就行。

程序:

import random
import sys
import time

from selenium import webdriver

# Powered By CC2001
# 学习通网课自动看视频,默认为每节课的第一个项目就是视频,如果不是可以自行修改“learn”函数

phone = ''  # 填入学习通手机号
password = ''  # 填入学习通密码
headLess = True  # 无头模式(不显示渲染浏览器),有头还是更稳定一些


def changeToIframeByX(xpath):
    iframe = driver.find_element_by_xpath(xpath)
    driver.switch_to.frame(iframe)  # 切换到iframe


def changeToIframeByID(frameID):
    iframe = driver.find_elements_by_id(frameID)
    driver.switch_to.frame(iframe[-1])  # 切换到iframe


def sleep():
    time.sleep(round(random.random(), 1) + 0.5)


def timeToS(timeStr):
    t = timeStr.strip().split(':')
    if len(t) == 2:
        mm, ss = t
        return int(mm) * 60 + int(ss)
    elif len(t) == 3:
        hh, mm, ss = t
        return int(hh) * 3600 + int(mm) * 60 + int(ss)


def getTime():
    return time.strftime('[%H:%M:%S]', time.localtime())


if headLess:
    EDGE = {
        "browserName": "MicrosoftEdge",
        "version": "",
        "platform": "WINDOWS",
        "ms:edgeOptions": {
            'extensions': [],
            'args': [
                '--headless',
            ]}
    }
else:
    EDGE = None

driver = webdriver.Edge(executable_path='msedgedriver.exe', capabilities=EDGE)  # executable_path为下载的Edge引擎的路径
driver.set_window_rect(-1000, -1000, 1000, 1000)
driver.implicitly_wait(5)
driver.get('https://passport2.chaoxing.com/login?fid=&newversion=true')  # 学习通登录界面

if phone == '':
    phone = input("学习通绑定的手机号:")
driver.find_element_by_id('phone').send_keys(phone)

if password == '':
    password = input("学习通密码:")
driver.find_element_by_id('pwd').send_keys(password)

sleep()
driver.find_element_by_id('loginBtn').click()

changeToIframeByX('/html/body/div[2]/div[2]/iframe')

subjects = driver.find_element_by_xpath(
    '/html/body/div[1]/div/div/div[2]/div/div[2]/div[2]/ul').find_elements_by_tag_name('li')

notNullSubjects = []
for s in subjects:
    if s.text != "":
        notNullSubjects.append(s)

for index, s in enumerate(notNullSubjects):
    print("[%d]:" % index, s.text.replace("\n", " "))
print("---------------------------------------------------")

inp = input("输入科目序号:")
try:
    inp = int(inp)
except ValueError:
    print("格式错误,即将退出")
    driver.quit()
    sys.exit()
else:
    notNullSubjects[inp].find_element_by_tag_name('a').click()
    notNullSubjects.clear()

handles = driver.window_handles  # 获取当前全部窗口句柄集合
for handle in handles:  # 切换窗口
    if handle != driver.current_window_handle:
        driver.close()  # 关闭第一个窗口
        driver.switch_to.window(handle)  # 切换到第二个窗口
driver.minimize_window()
driver.find_element_by_xpath('/html/body/div[1]/div[3]/div[1]/div/ul[1]/li[2]/a').click()

sleep()
changeToIframeByID('frame_content-zj')
classes = []
for x in driver.find_elements_by_xpath('/html/body/div[1]/div/div[2]/div[2]'):
    for index, xx in enumerate(x.find_elements_by_tag_name('li')):
        classes.append(xx)
        print("[%d]:" % index, xx.text.replace("\n", " 任务数:"))
classes.clear()
driver.switch_to.parent_frame()
print("---------------------------------------------------")


def learn(o):
    global driver
    sleep()
    changeToIframeByID('frame_content-zj')
    for c in driver.find_elements_by_xpath('/html/body/div[1]/div/div[2]/div[2]'):
        for index1, cc in enumerate(c.find_elements_by_tag_name('li')):
            if index1 == o:
                cc.click()
    sleep()
    driver.set_window_rect(-1000, -1000, 1000, 1000)
    changeToIframeByX('/html/body/div[4]/div/div[3]/div[5]/iframe')
    changeToIframeByX('/html/body/div/div/p[1]/div/iframe')
    driver.find_element_by_tag_name('button').click()
    sleep()
    print('%s正在播放编号为“%d”的课程' % (getTime(), o), end=': ')
    time.sleep(needTime() + 3)
    print('%s编号为“%d”的课程已播放完毕' % (getTime(), o))
    driver.switch_to.parent_frame()
    driver.switch_to.parent_frame()
    driver.find_element_by_xpath('/html/body/div[4]/div/div[1]/a').click()
    sleep()


def needTime():
    try:
        sleep()
        timeNow = driver.find_element_by_xpath('/html/body/div/div[4]/div/div[5]/div[2]/span[2]').text
        timeStop = driver.find_element_by_xpath('/html/body/div/div[4]/div/div[5]/div[4]/span[2]').text
        n = timeToS(timeStop) - timeToS(timeNow)
    except TypeError:
        print('进度获取失败,准备退出当前课程')
        return 1
    else:
        if n > 0:
            print('%s/%s,需要%d秒' % (timeNow, timeStop, n))
        driver.minimize_window()
        return n


print("可输入一个编号,或输入两个中间夹着“:”的编号(“a:b”代表[a,b])。输入其他格式可退出程序。")
inp = input("输入课程序号:")
if ":" in inp:
    inp = inp.split(":")
else:
    inp = inp.split(":")
if len(inp) == 1:
    try:
        s = int(inp[0])
    except ValueError:
        print("无法识别,即将退出")
    else:
        learn(s)

elif len(inp) == 2:
    s, e = inp
    try:
        s = int(s)
        e = int(e)
    except ValueError:
        print("无法识别,即将退出")
    else:
        if s > e:
            temp = s
            s = e
            e = temp
        for i in range(s, e + 1):
            learn(i)
        print("%s%d到%d所有课程播放完毕" % (getTime(), s, e))

driver.quit()

其他:

我没使过太久Python,写的可能有点怪,但还是差不多能跑的。逻辑上很简单,就是和脚本一样,得照着网页提前把处理方式录入好。善用“F12”,编起来没啥难度。需要使用的元素在iframe里的需要先切进去,切进去后的环境就是新的网页,用外面的东西时记得切出来。

科技改变生活😍




性感CC - 在线找打
------ 我是分割线 ------