卓越飞翔博客卓越飞翔博客

卓越飞翔 - 您值得收藏的技术分享站
技术文章11201本站已运行3223

Python 新版职教云自动学习脚本

一.前言
  该脚本用于智慧职教的自动学习,使用selenium框架以及requests库,代码中使用了许多面向过程写法,死循环等,欢迎有能力的大佬进行优化,共同学习。如若认为有些用处请给予回复与评分,欢迎指出不足缺点,共同进步,仅做个人学习使用,严禁用于其他用途。
二.开发环境
windows 11 Python 3.10 x86
三.调用模块
  1. import json
  2. import sys
  3. import time
  4. import requests
  5. import watch
  6. from prettytable import PrettyTable
  7. import random
  8. import time
  9. from lxml import etree
  10. from prettytable import PrettyTable
  11. from selenium import webdriver
  12. from selenium.webdriver.chrome.service import Service
  13. from selenium.webdriver.common.by import By
四.代码

#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()
 

#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()
卓越飞翔博客
上一篇: Python b站的爬虫视频真不错,分享自己跟着写的壁纸爬虫代码
下一篇: Python 获取双色球开奖信息并保存mysql数据库
留言与评论(共有 0 条评论)
   
验证码:
隐藏边栏