One 许增宝

超星助手开发文档及使用说明
本软件开发旨在解放双手,使用户更方便的听课,请勿用于刷网课,负责后果自负!其次本文档主要用于技术交流及学习,旨在说...
扫描右侧二维码阅读全文
20
2019/05

超星助手开发文档及使用说明

本软件开发旨在解放双手,使用户更方便的听课,请勿用于刷网课,负责后果自负!
其次本文档主要用于技术交流及学习,旨在说明技术实现以及探讨交流使用,由于说明原理需要,会用小篇幅说明使用方法!
若有不当,请联系我删除所有有关软件及文档!

最近更新

  • 2019.05.20:

    1. 修复网络线路选择闪退
    2. 修复判断题闪退
    3. 修复多选题闪退


本篇文章主要分为两个部分,一部分是介绍软件的实现原理,另一部分是介绍软件的使用说明!软件做了防检测处理,全程模仿鼠标点击浏览器,所以理论来说是不会被检测到不良记录,但是万事有意外,本人不敢做 100% 保证!你可以用本软件解放双手和PC设备听课,但是请勿用本软件刷课!



务必看使用说明 重要的事情说三行!
务必看使用说明 重要的事情说三行!
务必看使用说明 重要的事情说三行!

一、软件使用文档说明

1、主要功能说明:

  • 解放双手、PC: 可以在播放视频的同时做其他任何事情,视频不会停止
  • 自动跳转:  当视频播放结束后自动跳转到下一视频
  • 防检测:  软件采用的开源的浏览器自动化测试框架 Selenium,全程模仿真人操作,具体介绍可看百度百科,除此之外还加入了限时操作,避免频繁点击
    QQ截图20190512192333.png
  • 自动答题:  这里说的自动答题说的是视频播放时出现在视频上面的题目,当题目出现时,会自动选择正确答案进行提交答题

2、使用说明:

1、使用前提:  使用前务必把每节视频后面的章节检测先完成,然后再使用 超星助手 ,如下图:
QQ截图20190512194320.png



2、第一条前提保证后,你就可以使用超星助手了,先解压文件夹,安装ChromeSetup.exe(谷歌浏览器),若你电脑本身有Chrome浏览器,则只需要更新到最新版本即可,不必重新装!如下图黄色区域位置选择更新:
2019-05-12_195421.png


3、完成以上步骤后,直接打开 超星助手.exe ,会弹出小黑框,记住所有操作均是在小黑框里面操作,请勿在浏览器网页中有任何操作,按照小黑框提示输入需要的数据,每输入完一个数据按一次回车键结束本次输入,如果输入错误或者其他原因,导致小黑框闪退,重新打开即可!


4、打开后输入学校代码,这里给出几个学校的代码,其他学校请自己查相应的学校代码:

  • 安徽理工大学 12007
  • 安徽工业大学 465
  • 安徽财经大学 139
    现在具体演示下获取学校代码的方法,首先打开第二步安装的 Chrome 浏览器,然后输入超星尔雅链接,这里我给出 “http://passport2.chaoxing.com/login?fid=&refer=http://i.mooc.chaoxing.com”,复制这段链接去浏览器打开:
  1. 打开后选择学校:
    QQ截图20190512212658.png
  2. 输入你的学校名称并搜索,然后按 F12 键,看到如下图的 id 就是你的学校代码:

    • QQ截图20190512213035.png
    • QQ截图20190512213539.png

5、输入学校代码后,会自动打开浏览器窗口,然后根据提示输入就可以了,注意所有操作均在小黑框中进行,听网课的窗口可以拖到桌面拐角不管,也可以被覆盖,但是不建议最小化!

6、如登录不上,提示 “xxx错误” ,那么删除运行文件下的 Cookie.txt 文件在重新登录即可,这个文件是记录你登录状态的!

3、一般问题

 一般出现闪退情况是因为你做了不正规操作,比如关闭了小黑框,或者点击了正在播放视频的网页其他元素等等,否则不会出现问题的!

二、软件实现原理说明

(因为比较忙,所以直接贴代码了,重要的地方我写了注释)

模块对应功能:

  • Main: 程序入口模块
  • Login:处理登录等业务逻辑的模块
  • MyCourses:个人主页模块
  • CourseDetailes:课程详情模块,主要用于遍历列表未完成的课程
  • StartCourse:刷课模块,也是本程序最核心的模块,主要功能都在此模块内

Main代码:

package cn.onexzb.cxzs;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

import java.util.List;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) throws Exception {
        // 个人信息
        System.out.println("\n\n\n超星助手 启动成功!\n\n\n");
        System.out.println("        *********************************************************");
        System.out.println("                                                               ");
        System.out.println("                                                               ");
        System.out.println("         若你第一次使用此软件,请务必移步下面链接阅读使用说明:               ");
        System.out.println("                             https://www.onexzb.cn/317.html     ");
        System.out.println("                                                               ");
        System.out.println("         温馨提示:此软件旨在解放双手,请解放双手的同时认真听课!              ");
        System.out.println("                                                               ");
        System.out.println("                                                               ");
        System.out.println("                                                               ");
        System.out.println("        *********************************************************");
        @SuppressWarnings("resource")
        Scanner sc = new Scanner(System.in);
        System.out.print("\n\n\n请输入学校代码,按回车(Enter)键确认输入完毕:");
        String schid = sc.next();
        Login login = new Login(schid);   // 初始化登陆函数
        WebDriver driver = login.initDriver();
        // 获取课程列表
        List<WebElement> listcourses =  MyCourses.listCourses(driver);
        MyCourses.toCourseDatails(driver, listcourses);
        // 获取单科课程列表
        CourseDetails cd = new CourseDetails(driver);
        List<WebElement> single_list = cd.single_list;
        // 开始刷课
        StartCourse start_sc = new StartCourse(driver, single_list);
        start_sc.toCourse();
    }
}

Login 代码:

package cn.onexzb.cxzs;

import org.openqa.selenium.By;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.io.*;
import java.util.Date;
import java.util.Scanner;
import java.util.StringTokenizer;

public class Login {
    private String username;    // 用户名
    private String password;    // 密码
    private String schid;

    // 构造函数
    public Login(String schid) {
        this.schid = schid;
    }

    // 初始化 dirver 并实现登录功能
    public WebDriver initDriver() throws InterruptedException {
        System.setProperty("webdriver.chrome.driver", "E:\\IdeaProjects\\maven_cxey\\src\\main\\java\\cn\\onexzb\\cxzs\\chromedriver.exe");
        WebDriver driver = new ChromeDriver();
        userLogin(driver);      // 调用登陆函数
        return driver;
    }


    // 登录功能定义
    private void userLogin(WebDriver driver) throws InterruptedException {
        driver.get("http://passport2.chaoxing.com/login?fid="+schid+"&refer=http://i.mooc.chaoxing.com/");    // 打开目标 url
        // 判断Cookie是否存在
        File cookieFile = new File("Cookie.txt");
        if(cookieFile.exists()){
            System.out.println("\n系统检测到该程序保有您的登录信息,将自动登录!\n\n若登录失败,请删除该程序下的 Cookie.txt 文件后重新登录!\n\n");
            // 调用取出 Cookie 函数
            getCookie(driver);
            Thread.sleep(1000);
            driver.get("http://i.mooc.chaoxing.com/space");
        }
        else {

            WebDriverWait wait = new WebDriverWait(driver, 10);     // 每隔 0.5 秒检测一次
            WebElement user = wait.until(ExpectedConditions.presenceOfElementLocated(By.id("unameId")));
            WebElement pawd = wait.until(ExpectedConditions.presenceOfElementLocated(By.id("passwordId")));
            WebElement verc = wait.until(ExpectedConditions.presenceOfElementLocated(By.id("numcode")));
            @SuppressWarnings("resource")
            Scanner sc = new Scanner(System.in);
            System.out.print("\n\n请输入账号,按回车(Enter)键确认输入完毕:");
            username = sc.next();
            System.out.print("\n\n请输入密码,按回车(Enter)键确认输入完毕:");
            password = sc.next();
            user.sendKeys(username);    // 输入用户名
            pawd.sendKeys(password);    // 输入密码
            System.out.println("\n温馨提示:\n若由于账号、密码或验证码错误程序报错,请删除 Cookie.txt 文件再重新打开程序登录!\n");
            System.out.print("\n请输入浏览器显示的验证码:");
            String vercode = sc.next();
            verc.sendKeys(vercode);     // 输入验证码
            driver.findElement(By.className("zl_btn_right")).click(); // 点击登录
            setCookie(driver);
        }
    }

    // 存储Cookie
    private void setCookie(WebDriver driver){
        File cookieFile = new File("Cookie.txt");
        try {
            cookieFile.delete();
            cookieFile.createNewFile();
            FileWriter fileWriter = new FileWriter(cookieFile);
            BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
            for (Cookie cookie:driver.manage().getCookies()){
                bufferedWriter.write((cookie.getName()+";"+
                        cookie.getValue()+";"+
                        cookie.getDomain()+";"+
                        cookie.getPath()+";"+
                        cookie.getExpiry()+";"+
                        cookie.isSecure()));
                bufferedWriter.newLine();
            }
            bufferedWriter.flush();
            bufferedWriter.close();
            fileWriter.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    // 取出Cookie
    @SuppressWarnings("deprecation")
    private  void getCookie(WebDriver driver){
        try {
            File cookieFile = new File("Cookie.txt");
            FileReader fileReader = new FileReader(cookieFile);
            @SuppressWarnings("resource")
            BufferedReader bufferedReader = new BufferedReader(fileReader);
            String line;
            while ((line = bufferedReader.readLine()) != null){
                StringTokenizer stringTokenizer = new StringTokenizer(line, ";");
                while (stringTokenizer.hasMoreTokens()){
                    String name = stringTokenizer.nextToken();
                    String value = stringTokenizer.nextToken();
                    String domain = stringTokenizer.nextToken();
                    String path = stringTokenizer.nextToken();
                    Date expiry = null;
                    String dt;
                    if (!(dt = stringTokenizer.nextToken()).equals("null")){
                        expiry = new Date(dt);
                    }
                    boolean isSecure = new Boolean(stringTokenizer.nextToken()).booleanValue();
                    Cookie cookie = new Cookie(name, value,domain,path,expiry,isSecure);
                    driver.manage().addCookie(cookie);
                }
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

MyCourses 代码:

package cn.onexzb.cxzs;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Set;

public class MyCourses {
    // 获取课程列表
    public static ArrayList<WebElement> listCourses(WebDriver driver) throws InterruptedException {
        WebElement frame = driver.findElement(By.xpath("//*[@id=\"frame_content\"]"));      // 定位 iframe
        driver.switchTo().frame(frame);     // 切换到 frame
        Thread.sleep(1000);
        List<WebElement> listcourses = driver.findElements(By.cssSelector("html > body > div > div > div > ul > li > div > h3 > a"));
        Thread.sleep(1000);
        return (ArrayList<WebElement>) listcourses;
    }

    // 课程详情
    public static void toCourseDatails(WebDriver driver, List<WebElement> listcourses){
        String courses_handle = driver.getWindowHandle();       // 获取当前窗口句柄
        for(int i = 0; i < listcourses.size(); i++){
            System.out.println(i+1 +" : " + listcourses.get(i).getText());
        }
        @SuppressWarnings("resource")
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入你想看的课程的序号,按回车(Enter)键确认输入完毕:");
        // 防止用户输入错误
        try{
            int i = sc.nextInt();
            listcourses.get(i-1).click();
            Thread.sleep(1000);
        }
        catch (Exception e){
            System.out.println("您的输入不合法!");
        }
        // 获取所有窗口句柄
        Set<String> handles = driver.getWindowHandles();
        // 切换到新打开的窗口
        for (String handle:handles){
            if(handle.equals(courses_handle) == false){
                driver.switchTo().window(handle);
                break;
            }
        }


    }
}

CourseDatails 模块:

package cn.onexzb.cxzs;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

import java.util.ArrayList;
import java.util.List;

public class CourseDetails {
    public ArrayList<WebElement> single_list;      // 课程列表

    public CourseDetails(WebDriver driver) {
        List<WebElement> list_a = driver.findElements(By.cssSelector("html > body > div > div > div > div > div > div > h3 > span > a"));
        List<WebElement> list_em = driver.findElements(By.xpath("/html/body/div/div/div/div/div/div/h3/span/em"));
        single_list = (ArrayList<WebElement>) list_a;
        int success = 0;
        for (int i = 0; i < list_em.size(); i++){
            if(list_em.get(i).getAttribute("class").equals("openlock")){
                list_a.remove(i-success);
                success++;
            }
        }
        System.out.println("\n您本门课程有 " + success + " 集已经完成,下面将从您未完成的课程开始播放!");
    }

    public static List<WebElement> reList (WebDriver driver){
        System.out.println("刷新列表");
        List<WebElement> list_a = driver.findElements(By.cssSelector("html > body > div > div > div > div > div > div > h3 > span > a"));
        List<WebElement> list_em = driver.findElements(By.cssSelector("html > body > div > div > div > div > div > div > h3 > span > em"));
        int success = 0;
        for (int i = 0; i < list_em.size(); i++){
            if(list_em.get(i).getAttribute("class").equals("openlock")){
                list_a.remove(i-success);
                success++;
            }
        }
        System.out.println("列表刷新完毕");
        return list_a;
    }
}

StartCourse 代码:

package cn.onexzb.cxzs;

import org.openqa.selenium.*;
import org.openqa.selenium.interactions.Actions;

import java.util.List;

public class StartCourse {
    private WebDriver driver;       // 需要传入 driver
    private List<WebElement> lists; // 传入单科课程列表

    public StartCourse(WebDriver driver, List<WebElement> lists) {
        this.driver = driver;
        this.lists = lists;
    }

    public void toCourse() throws Exception {
        while (lists.size() != 0){
            // 重新获取列表
            System.out.println("即将播放视频" + lists.get(0).getAttribute("title"));
            lists.get(0).click();
            // 获取标题下小元素个数
            List<WebElement> span_title = driver.findElements(By.cssSelector("html > body > div > div > div > div > span"));
            System.out.println("选择视频窗口");
            if (span_title.size() == 3) {
                span_title.get(1).click();
            }
            Thread.sleep(3000);
            startVideo();
            Thread.sleep(2000);
            lists = CourseDetails.reList(driver);
        }
        System.out.println("该门课程已经刷完!");
    }
    // 开始刷课,包含处理 frame 和中场选择题
    public void startVideo() throws Exception {
        WebElement frame1 = driver.findElement(By.xpath("//*[@id=\"iframe\"]"));
        driver.switchTo().frame(frame1);        // 选择 frame1
        WebElement frame2 = driver.findElement(By.xpath("//*[@id=\"ext-gen1039\"]/iframe"));
        driver.switchTo().frame(frame2);        // 选择 frame2
        WebElement start_video = driver.findElement(By.xpath("//*[@id=\"video\"]/button"));         // 开始播放视频
        System.out.println("即将开始播放视频");
        Thread.sleep(3000);

        Actions actions =  new Actions(driver);
        actions.moveToElement(start_video).perform();
        Thread.sleep(1000);
        start_video.click();
        Thread.sleep(3000);
        WebElement assit = driver.findElement(By.xpath("//*[@id=\"video\"]/div[4]/button[1]"));
        System.out.println("辅助鼠标执行完成");

        while (true){
            Actions action_assit = new Actions(driver);
            action_assit.moveToElement(assit).perform();
            // 线路选择
            if (circuit())
                System.out.println("线路选择完毕!");
            // 执行答题
            solvePro();
            // 是否暂停
            isPause(assit);
            // 播放进度以及是否完成
            if(rOP())
                return;

        }

    }

    // 判断元素是否存在
    private boolean elementExist(By locator){
        try{
            driver.findElement(locator).isDisplayed();
            return true;
        }catch(Exception e){
            return false;
        }
    }

    // 检测视频播放了多少以及是否播放完
    private boolean rOP() throws InterruptedException {
        if (elementExist(By.xpath("//*[@id=\"video\"]/div[4]/div[5]/div"))){
            WebElement rate = driver.findElement(By.xpath("//*[@id=\"video\"]/div[4]/div[5]/div"));
            System.out.println("本集已完成 %" + rate.getAttribute("aria-valuenow"));
            if (rate.getAttribute("aria-valuenow").equals("100.00")){
               toSwitch();
                return true;
            }
        }
        if (elementExist(By.xpath("//*[@id=\"video\"]/div[4]/div[1]"))){
            WebElement finsh = driver.findElement(By.xpath("//*[@id=\"video\"]/div[4]/div[1]"));
            if (finsh.getAttribute("class").equals("vjs-playback-rate vjs-menu-button vjs-menu-button-popup vjs-control vjs-button")) {
               toSwitch();
                return true;
            }
        }
        return false;
    }

    // 检测视频是否暂停了
    private void isPause(WebElement assit) throws Exception {
        if (elementExist(By.xpath("//*[@id=\"video\"]/div[4]/button[1]/span[2]"))){
            WebElement pause = driver.findElement(By.xpath("//*[@id=\"video\"]/div[4]/button[1]/span[2]"));
            if (pause.getText().equals("播放"))
                try {
                    assit.click();
                }catch (Exception e){
                    return;
                }
        }
    }

    // 答题
    private void solvePro() throws InterruptedException {
        // 答选择题
        if(elementExist(By.xpath("//*[@id=\"videoquiz-1037\"]/ul/li/label/input"))){
            List<WebElement> choices = driver.findElements(By.xpath("//*[@id=\"videoquiz-1037\"]/ul/li/label/input"));
            //*[@id="videoquiz-1039"]/ul/li/label/input
            WebElement submit = driver.findElement(By.xpath("//*[@id=\"ext-gen1045\"]"));
            for (WebElement choice:choices)
            {
                System.out.println(choice.getAttribute("value"));
                if (choice.getAttribute("value").equals("true"))
                    choice.click();
            }
            Thread.sleep(1000);
            submit.click();
            System.out.println("选择题解答完毕!");
        }
        // 答判断题
        if (elementExist(By.cssSelector("html > body > div > div > div > span > div > div > ul > li > label > input"))){
            List<WebElement> choices = driver.findElements(By.cssSelector("html > body > div > div > div > span > div > div > ul > li > label > input"));
            WebElement submit = driver.findElement(By.className("ans-videoquiz-submit"));
            for (WebElement choice:choices){
                System.out.println(choice.getAttribute("value"));
                if (choice.getAttribute("value").equals("true"))
                    choice.click();
            }
            Thread.sleep(1000);
            submit.click();
            System.out.println("判断题解答完毕!");
        }
    }

    // 线路选择
    private boolean circuit() throws Exception {
        try {
            List<WebElement> cir = driver.findElements(By.cssSelector("html > body > div > div > div > div > ul > li > label > input"));
            for (int i = 1; i < cir.size(); i++){
                if(cir.get(i).isEnabled()){
                    cir.get(i).click();
                    Thread.sleep(1000);
                    return true;
                }
            }
            return false;
        }catch (Exception e){
            return false;
        }
    }

    // 跳转视频
    private void toSwitch() throws InterruptedException {
        System.out.println("检测到该任务已完成!30s 后自动切换到下一任务!");
        driver.switchTo().parentFrame();
        Thread.sleep(5000);
        driver.switchTo().parentFrame();
        Thread.sleep(5000);
        driver.findElement(By.xpath("/html/body/div[3]/div/div[1]/a")).click();
        Thread.sleep(3000);
    }
}

有任何不懂得地方可以探讨交流,或者你有任何建议也行,联系方式QQ:676807890!

最后修改:2019 年 05 月 29 日 01 : 03 PM

发表评论