【Python原创】新版职教云自动学习脚本 · selenium

查看 82|回复 9
作者:Pastwill   
一.前言
  该脚本用于智慧职教的自动学习,使用selenium框架以及requests库,代码中使用了许多面向过程写法,死循环等,欢迎有能力的大佬进行优化,共同学习。如若认为有些用处请给予回复与评分,欢迎指出不足缺点,共同进步,仅做个人学习使用,严禁用于其他用途。
二.开发环境
windows 11 Python 3.10 x86
三.调用模块
[Python] 纯文本查看 复制代码import json
import sys
import time
import requests
import watch
from prettytable import PrettyTable
[Python] 纯文本查看 复制代码import random
import time
from lxml import etree
from prettytable import PrettyTable
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
四.代码
[Python] 纯文本查看 复制代码#app.py
import json
import sys
import time
import requests
from prettytable import PrettyTable
import watch
# 全局变量区
userName = ""
password = ""
'''
控制台日志输出脚本
'''
def out(text):
    print(time.strftime(f"[%Y-%m-%d %H:%M:%S]:{text}", time.localtime()))
'''
登陆并返回token
'''
def login():
    payload = {
        "userName": userName,
        "password": password,
        "type": 1
    }
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"}
    token = json.loads(
        requests.request("POST", "https://sso.icve.com.cn/data/userLogin", json=payload, headers=headers).text)
    if token["msg"] == "ok":
        out("恭喜登陆成功!")
        global oktoken
        oktoken = token["data"]
    else:
        out("登陆失败!")
        sys.exit()
    out("开始尝试登陆!")
    payload = f'token={token["data"]}'
    headers = {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}
    info = json.loads(
        requests.request("POST", "https://user.icve.com.cn/patch/zhzj/api_getUserInfo.action", headers=headers,
                         params=payload).text)
    if "成功" in info['errorMsg']:
        out("个人信息获取成功")
        table = PrettyTable(["姓名", "学号", "城市", "学校"])
        table.add_row([info['data']['displayName'], info['data']['employeeNumber'], info['data']['province'],
                       info['data']["schoolName"]])
        print(table)
    out("开始获取课程信息!")
    url = "https://user.icve.com.cn/learning/u/userDefinedSql/getBySqlCode.json"
    payload = "data=info&page.searchItem.queryId=getStuCourseInfoById&page.searchItem.keyname=&page.curPage=1&page.pageSize=500"
    headers = {
        "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
        "Cookie": f"token={oktoken};",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"
    }
    info = json.loads(requests.request("POST", url, data=payload, headers=headers).text)
    classok = []
    k = 0
    table = PrettyTable(["编号", "课程名", "任课教师", "课程ID"])
    for i in info["page"]["items"][0]['info']:
        classok.append([i["ext1"], i["ext4"], i["ext9"]])
        table.add_row([k, i["ext1"], i["ext4"], i["ext9"]])
        k = k + 1
    print(table)
    watch.Watch(userName, password, classok[int(input("请选择您要执行的课程编号"))][2])
if __name__ == '__main__':
    login()
[Python] 纯文本查看 复制代码#watch.py
import random
import time
from lxml import etree
from prettytable import PrettyTable
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
def out(text):  # 格式输出
    print(time.strftime(f"[%Y-%m-%d %H:%M:%S]:{text}", time.localtime()))
def Watch(userName, password, classId):
    options = webdriver.ChromeOptions()
    options.add_experimental_option('excludeSwitches', ['enable-automation'])
    # 屏蔽以开发者运行提示框
    options.add_experimental_option('useAutomationExtension', False)
    # 屏蔽保存密码提示框
    prefs = {'credentials_enable_service': False, 'profile.password_manager_enabled': False}
    options.add_experimental_option('prefs', prefs)
    # chrome 88 或更高版本的反爬虫特征处理
    options.add_argument('--disable-blink-features=AutomationControlled')
    # 浏览器对象
    preferences = {
        "webrtc.ip_handling_policy": "disable_non_proxied_udp",
        "webrtc.multiple_routes_enabled": False,
        "webrtc.nonproxied_udp_enabled": False
    }
    # 关闭webrtc 避免找到真实IP地址
    options.add_experimental_option("prefs", preferences)
    options.binary_location = r'Chrome\App\Chrome.exe'
    driver = webdriver.Chrome(service=Service(r'chromedriver.exe'), options=options)
    with open('stealth.min.js', mode='r', encoding='utf-8') as f:
        string = f.read()
    # 移除 selenium 中的爬虫特征
    driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {'source': string})
    driver.get('https://sso.icve.com.cn/sso/auth?mode=simple&source=2&redirect=https://user.icve.com.cn/cms/')
    time.sleep(1)
    driver.find_element(By.ID, 'userName').send_keys(userName)
    time.sleep(1)
    driver.find_element(By.ID, 'password11').send_keys(password)
    time.sleep(1)
    driver.find_element(By.ID, 'isTy').click()
    time.sleep(1)
    driver.find_element(By.CLASS_NAME, 'dl').click()
    time.sleep(1)
    try:
        driver.find_element(By.ID, 'close1').click()
        time.sleep(1)
        driver.find_element(By.ID, 'close2').click()
        time.sleep(1)
        driver.find_element(By.ID, 'close3').click()
        time.sleep(1)
        driver.find_element(By.ID, 'close4').click()
    except:
        out("预防性点击可能出现的提示框")
    time.sleep(4)
    if "* 校验登录状态" in driver.page_source:
        time.sleep(3)
        driver.find_element(By.ID, 'userCenterUrl').click()
        out("登录成功")
        driver.get(
            f"https://course.icve.com.cn/learnspace/sign/signLearn.action?template=blue&courseId={classId}&loginType=true&loginId={userName}&sign=0&siteCode=zhzj&domain=user.icve.com.cn")
        time.sleep(2)
        driver.switch_to.frame('mainContent')
        time.sleep(2)
        videotasker = etree.HTML(driver.page_source).xpath('//*[@completestate="0" and @itemtype="video"]/@onclick')
        doctasker = etree.HTML(driver.page_source).xpath('//*[@completestate="0" and @itemtype="doc"]/@onclick')
        vodall = len(etree.HTML(driver.page_source).xpath('//*[@itemtype="video"]/@onclick'))
        docall = len(etree.HTML(driver.page_source).xpath('//*[@itemtype="doc"]/@onclick'))
        table = PrettyTable(["视频已完成/全部", "文档已完成/全部", "总进度"])
        table.add_row([f"{vodall - len(videotasker)}/{vodall}", f"{docall - len(doctasker)}/{docall}",
                       '{:.2%}'.format((len(videotasker) + len(doctasker)) / (vodall + docall))])
        print(table)
        out("开始执行视频任务序列")
        for i in videotasker:
            time.sleep(2)
            driver.execute_script(i)
            while True:
                if 'id="mainFrame" name="mainFrame"' in driver.page_source:  # 利用死循环进入播放器框架 吐槽一下职教云辣鸡代码
                    driver.switch_to.frame('mainFrame')
                    break
            while True:
                time.sleep(random.randint(3, 7))
                look = driver.execute_script(
                    'return document.getElementById("screen_player_time_1").textContent')
                print(f'观看:{driver.execute_script("return document.title")} 已观看到{look}')
                time.sleep(10)  # 十秒输出
                if look == driver.execute_script(
                        'return document.getElementById("screen_player_time_2").textContent'):
                    out("观看完成,即将下一个")
                    driver.switch_to.parent_frame()
                    break
        out("开始执行文档任务序列")
        for i in doctasker:
            time.sleep(2)
            driver.execute_script(i)
            print(f'观看:{driver.execute_script("return document.title")}')
            time.sleep(7)
            out("观看完成,即将下一个")
        videotasker = etree.HTML(driver.page_source).xpath('//*[@completestate="0" and @itemtype="video"]/@onclick')
        doctasker = etree.HTML(driver.page_source).xpath('//*[@completestate="0" and @itemtype="doc"]/@onclick')
        vodall = len(etree.HTML(driver.page_source).xpath('//*[@itemtype="video"]/@onclick'))
        docall = len(etree.HTML(driver.page_source).xpath('//*[@itemtype="doc"]/@onclick'))
        if (len(videotasker) + len(doctasker)) == (vodall + docall):
            out("恭喜 本课全部观看完成 程序退出!")
            exit()
github: https://github.com/Past-GuoWang/icvepass
完整环境:https://www.123pan.com/s/CW2DVv-deHBh.html提取码:s6ZU

微软, 代码

xilihutu   

哇!好厉害!谢谢!
Z65156811   

有点6,可以搞其他学习平台的就更牛了
endriver   

感谢分享,学习了
MortyS   

感谢分享,学习一下思路
shitdevops   

牛的牛的 学习了
dreamact   

我靠,为什么不早点出
wertop   

谢谢分享
zhaoaa   

要是有个学习通,我爱死你了
15310062345   

谢谢分享
您需要登录后才可以回帖 登录 | 立即注册

返回顶部