吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5369|回复: 22
收起左侧

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

  [复制链接]
Pastwill 发表于 2023-4-2 18:56
本帖最后由 Pastwill 于 2023-4-2 18:57 编辑

一.前言

  该脚本用于智慧职教的自动学习,使用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

免费评分

参与人数 9吾爱币 +15 热心值 +8 收起 理由
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
a22488 + 1 + 1 热心回复!
winsign + 1 + 1 我很赞同!
ydop + 1 + 1 我很赞同!
jhy0117 + 1 + 1 谢谢@Thanks!
echoaku + 1 + 1 谢谢@Thanks!
石淞元 + 1 已经下载好好学习下,谢谢
Colorfulone + 1 + 1 用心讨论,共获提升!
yjn866y + 1 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Z65156811 发表于 2023-4-2 20:00
有点6,可以搞其他学习平台的就更牛了
endriver 发表于 2023-4-2 20:09
MortyS 发表于 2023-4-2 20:35
shitdevops 发表于 2023-4-2 20:56
牛的牛的 学习了
dreamact 发表于 2023-4-2 21:27
我靠,为什么不早点出
zhaoaa 发表于 2023-4-2 22:05
要是有个学习通,我爱死你了
yahoo1920 发表于 2023-4-3 10:27
非常不错哦,学习了!!!
Wattiro 发表于 2023-4-3 21:29
感谢大佬!!
爱奴 发表于 2023-4-3 22:43
谢谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 17:16

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表