123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848 |
- package student
- import (
- "bufio"
- "bytes"
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "io/ioutil"
- "net/http"
- "os"
- "ouchn/config"
- "runtime"
- "strings"
- "time"
- "github.com/tebeka/selenium"
- "github.com/tebeka/selenium/chrome"
- "github.com/tidwall/gjson"
- )
- func GetRecord(filename string) map[string]bool {
- ret := map[string]bool{}
- fi, err := os.Open(filename)
- if err != nil {
- return ret
- }
- defer fi.Close()
- br := bufio.NewReader(fi)
- for {
- a, _, c := br.ReadLine()
- //fmt.Printf("xx:%s\n", a)
- if c == io.EOF {
- break
- }
- array := strings.Split(string(a), " ")
- if len(array) != 3 {
- continue
- }
- ret[array[0]] = true
- }
- return ret
- }
- func GetAcounts(filename string) ([][]string, error) {
- visited := GetRecord("record.txt")
- fi, err := os.Open(filename)
- if err != nil {
- return nil, err
- }
- defer fi.Close()
- ret := [][]string{}
- br := bufio.NewReader(fi)
- for {
- a, _, c := br.ReadLine()
- if c == io.EOF {
- break
- }
- array := strings.Split(string(a), ";")
- if len(array) != 3 {
- continue
- }
- if visited[array[0]] {
- //fmt.Printf("visited:%v\n", array[2])
- continue
- }
- item := []string{array[0], array[1], array[2]}
- ret = append(ret, item)
- }
- return ret, nil
- }
- func Displayed(by, elementName string) func(selenium.WebDriver) (bool, error) {
- return func(wd selenium.WebDriver) (ok bool, err error) {
- var el selenium.WebElement
- el, err = wd.FindElement(by, elementName)
- if err != nil {
- ok = false
- err = nil
- return
- }
- ok, err = el.IsDisplayed()
- return
- }
- }
- func Check415Error(wd selenium.WebDriver) error {
- e, err := wd.FindElement(selenium.ByTagName, "body")
- if err != nil {
- return err
- }
- text, _ := e.Text()
- str := "错误代码:415"
- if len(text) <= len(str) {
- return nil
- }
- if text[:len(str)] == str {
- return errors.New("访问受限")
- }
- return nil
- }
- func StartOneStudent(usernameText string, passwordText string, realName string) (*selenium.Service, selenium.WebDriver, error) {
- var (
- //driverPath = `C:\Users\lqzlt\AppData\Local\Google\Chrome\Application\chromedriver.exe`
- driverPath = `chromedriver.exe`
- port = 60002
- )
- // chrome服务
- service, err := selenium.NewChromeDriverService(driverPath, port, []selenium.ServiceOption{}...)
- if nil != err {
- return nil, nil, err
- }
- defer func() {
- //_ = service.Stop()
- }()
- // Connect to the WebDriver instance running locally.
- caps := selenium.Capabilities{"browserName": "chrome"}
- imagCaps := map[string]interface{}{
- //"profile.managed_default_content_settings.images": 2,
- //"profile.default_content_setting_values":2,
- "same-site-by-default-cookies": 2,
- "cookies-without-same-site-must-be-secure": 2,
- }
- chromeCaps := chrome.Capabilities{
- Prefs: imagCaps,
- Path: "",
- ExcludeSwitches: []string{"enable-automation"},
- //Extensions:[]string{"D:\\sql2struct"},
- Args: []string{
- //"--headless",
- //"--disable-javascript",
- "--disable-blink-features=AutomationControlled",
- "--no-sandbox",
- "--disable-gpu-sandbox",
- "--accept-Encoding=gzip, deflate",
- "--accept-language=zh-CN,zh;q=0.9,zh-TW;q=0.8,en-US;q=0.7,en;q=0.6",
- "--cache-control=max-age=0",
- "--abc=d",
- "--load-extention=D:\\sql2struct",
- //"--cookie=MoodleSession=66925citrm0o6b68gsfn9quaof;username=2051101450211;UserName=2051101450211",
- "--moodleSession=66925citrm0o6b68gsfn9quaof;username=2051101450211",
- "--upgrade-insecure-requests=1",
- //"--authorization=Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IkYyREVCM0ZGMURBMUFEODNFOTA5QjIxMjM4QTZCMjU5RjAyQjNGMDEiLCJ0eXAiOiJKV1QiLCJ4NXQiOiI4dDZ6X3gyaHJZUHBDYklTT0theVdmQXJQd0UifQ.eyJuYmYiOjE2MzYwMTAzNTMsImV4cCI6MTYzNjAxMzk1MywiaXNzIjoiaHR0cDovL3Bhc3Nwb3J0Lm91Y2huLmNuIiwiYXVkIjpbImh0dHA6Ly9wYXNzcG9ydC5vdWNobi5jbi9yZXNvdXJjZXMiLCJvdWNobnN0dWRlbnRzcGFjZWFwaSJdLCJjbGllbnRfaWQiOiJzdHVkZW50c3BhY2UiLCJzdWIiOiJlZjkzZTdlYi0zYjhlLTQ2ZTUtYjA1ZC1mYTJmYjAwYjA2ZmUiLCJhdXRoX3RpbWUiOjE2MzYwMTAyMDMsImlkcCI6ImxvY2FsIiwibmFtZSI6IjIwNTExMDE0NTAyMTEiLCJVc2VySWQiOiJlZjkzZTdlYi0zYjhlLTQ2ZTUtYjA1ZC1mYTJmYjAwYjA2ZmUiLCJVc2VyTmFtZSI6IjIwNTExMDE0NTAyMTEiLCJuaWNrbmFtZSI6IueOi-aVjyIsIkF2YXRhciI6IiIsIlVzZXJUeXBlIjoiMiIsIlByb3ZpbmNlU2Nob29sQ29kZSI6IjUxMSIsIk9yZ2FuaXphdGlvbkNvZGUiOiI1MTE1NDAwIiwiTW9iaWxlQ29uZmlybWVkIjoiRmFsc2UiLCJzY29wZSI6WyJvcGVuaWQiLCJwcm9maWxlIiwib3VjaG51c2VyIiwib3VjaG5zdHVkZW50c3BhY2VhcGkiLCJvZmZsaW5lX2FjY2VzcyJdLCJhbXIiOlsicHdkIl19.ACwdaY50NnuXiQso4T6dS1PoQc7K2rTBRKWz0VmocC40xL4PlPy3Usf3kAZf-1dNFnh8PTBUWc9s_F6eTp_Rcemu5IBGL-iKs9I-QMeG3u7TnaNbCL4XwUt8vZoOPHaXzor3gN7WEqs01Qj11nTbERZ2ixEMhk2Ov_lGqCS8me67pyvd2HWCP7yUcizfEk4_5FQBZZ12daRpXrBksCC27I8BcpXQLrogWewa1W4x5uhLFeW7BKhBGxYDT4yM-b0RNM2jNTxn-ToqoOgBIsLsnU8e0eOKi6WBuhbDYK8psiCPt1hT_3BumeuJ-P36iuaPLcNv7D2T1WlCMHJe1Fv92Q",
- "--connection=keep-alive",
- //"--host=chengdu.ouchn.cn",
- "--accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
- "--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36",
- },
- }
- //以上是设置浏览器参数
- caps.AddChrome(chromeCaps)
- wd, err := selenium.NewRemote(caps, fmt.Sprintf("http://localhost:%d/wd/hub", port))
- if err != nil {
- return service, nil, errors.New(fmt.Sprintf("connect to the webDriver failed:%v\n", err))
- }
- defer func() {
- //_ = wd.Close()
- }()
- //wd.Get("file:///C:/Users/lqzlt/Desktop/1.html")
- //time.Sleep(1*time.Second)
- //handleQuestionWebTest(wd)
- //time.Sleep(1000*time.Second)
- //return service, wd, nil
- err = wd.Get("https://menhu.pt.ouchn.cn/")
- if err != nil {
- return service, wd, err
- }
- // 进入登录页面
- err = wd.WaitWithTimeout(Displayed(selenium.ByName, "button"), 5*time.Second)
- if err != nil {
- return service, wd, errors.New(fmt.Sprintf("获取登录页面失败:%v\n", err))
- }
- username, err := wd.FindElement(selenium.ByID, "loginName")
- if err != nil {
- return service, wd, errors.New(fmt.Sprintf("获取用户名按钮:%v\n", err))
- }
- password, err := wd.FindElement(selenium.ByID, "password")
- if err != nil {
- return service, wd, errors.New(fmt.Sprintf("获取密码按钮:%v\n", err))
- }
- submit, err := wd.FindElement(selenium.ByName, "button")
- if err != nil {
- return service, wd, errors.New(fmt.Sprintf("获取登录按钮:%v\n", err))
- }
- err = username.SendKeys(usernameText)
- if err != nil {
- return service, wd, errors.New(fmt.Sprintf("填充用户名:%v\n", err))
- }
- err = password.SendKeys(passwordText)
- if err != nil {
- return service, wd, errors.New(fmt.Sprintf("填充密码:%v\n", err))
- }
- verifyCode, err := wd.FindElement(selenium.ByID, "validateCode")
- if err != nil {
- return service, wd, errors.New(fmt.Sprintf("获取验证码按钮失败:%v\n", err))
- }
- count := 0
- for count < 60 {
- time.Sleep(1*time.Second)
- value, _ := verifyCode.GetAttribute("value")
- if len(value) < 4 {
- continue
- }
- break
- }
- if count >= 60 {
- return service, wd, errors.New("未输入验证码")
- }
- err = submit.Click()
- if err != nil {
- return service, wd, errors.New(fmt.Sprintf("点击登录:%v\n", err))
- }
- //time.Sleep(1200 *time.Second)
- //return service, wd, errors.New("登录测试")
- // 进入学生主页
- err = wd.WaitWithTimeout(Displayed(selenium.ByXPATH, "//a[text()='去学习']"), 5*time.Second)
- if err != nil {
- return service, wd, errors.New(fmt.Sprintf("进入学生主页失败:%v\n", err))
- }
- buttons, _ := wd.FindElements(selenium.ByXPATH, "//a[text()='去学习']")
- currentWindow, err := wd.CurrentWindowHandle()
- if err != nil {
- return service, wd, errors.New(fmt.Sprintf("获取当前窗口失败:%v\n", err))
- }
- for _, button := range buttons {
- text, _ := button.Text()
- if text != "去学习" {
- continue
- }
- button.Click()
- //time.Sleep(60*time.Second)
- count := 0
- handled := ""
- // 等待新页面弹出
- for count < 5 {
- time.Sleep(1 * time.Second)
- handles, _ := wd.WindowHandles()
- if len(handles) > 1 {
- handled = handles[len(handles)-1]
- //
- wd.SwitchWindow(handled)
- break
- }
- count++
- }
- if count > 5 {
- continue
- }
- if err := Check415Error(wd); err != nil {
- return service, wd, err
- }
- // 处理课程
- err = CourseHandle(wd, realName)
- fmt.Printf("xxxxerr:%v\n", err)
- // 关闭当前课程窗口
- wd.CloseWindow(handled)
- // 切换到学生主页窗口(有进入学习按钮的窗口)
- wd.SwitchWindow(currentWindow)
- runtime.GC()
- }
- return service, wd, err
- }
- // 等待url变化
- func waitUrl(wd selenium.WebDriver, url1 string, url2 string, count int) string {
- for count >= 0 {
- time.Sleep(100 * time.Millisecond)
- url, _ := wd.CurrentURL()
- if url != url1 && url != url2 {
- return url
- }
- count--
- }
- return ""
- }
- func getCookies(wd selenium.WebDriver) (string, error) {
- cookies, err := wd.GetCookies()
- if err != nil {
- return "", errors.New(fmt.Sprintf("获取cookie 失败,%v\n", err))
- }
- if len(cookies) == 0 {
- return "", errors.New(fmt.Sprintf("获取cookie 失败,%v\n", "cookie为空"))
- }
- ret := ""
- for _, v := range cookies {
- item := fmt.Sprintf("%s=%s", v.Name, v.Value)
- if ret == "" {
- ret = item
- continue
- }
- ret = ret + ";"
- ret = ret + item
- }
- return ret, nil
- }
- func checkCourseExist(courses []string, course string) bool {
- for _, v := range courses {
- if v == course {
- return true
- }
- }
- return false
- }
- type RadioInfo struct {
- Radio selenium.WebElement
- }
- type AnswerInfo struct {
- Text string
- Radio *RadioInfo
- }
- type QuestionInfo struct {
- Text string
- Tag int
- Number string
- AnswerArray []*AnswerInfo
- ChoosedAnswer *AnswerInfo
- }
- func chooseAnswer(questions []QuestionInfo, questionM map[string][]string) error {
- for i, _ := range questions {
- if len(questions[i].AnswerArray) == 0 {
- return errors.New(fmt.Sprintf("%s 选项为空", questions[i].Text))
- }
- str := TrimSpace(questions[i].Text)
- str = ParseHan(str)
- str = fmt.Sprintf("%d-", questions[i].Tag) + str
- answerstrs, _ := questionM[str]
- if len(answerstrs) == 0 || answerstrs[0] == "" {
- return errors.New(fmt.Sprintf("%s 题库答案为空", questions[i].Text))
- }
- find := false
- answerstr := answerstrs[0]
- for _, v := range questions[i].AnswerArray {
- if strings.Contains(answerstr, TrimSpace(v.Text)) {
- v.Radio.Radio.Click()
- find = true
- break
- }
- }
- if !find {
- fmt.Printf("题库中的答案:%s\n", answerstr)
- for _, v := range questions[i].AnswerArray {
- fmt.Printf("选项:%v,%v\n", v.Text, strings.Contains(answerstr, v.Text))
- }
- return errors.New(fmt.Sprintf("%s 未找到匹配答案", questions[i].Text))
- }
- }
- return nil
- }
- func getCourseId(src string) string {
- array := strings.Split(src, "/")
- if len(array) < 5 {
- return ""
- }
- return array[4]
- }
- type CourseModule struct {
- Name string
- ModuleId string
- }
- func getCourseModules(courceId string, cookie string) ([]CourseModule, error) {
- url := fmt.Sprintf("https://lms.ouchn.cn/api/courses/%s/modules", courceId)
- request, err := http.NewRequest("GET", url, nil)
- if err != nil {
- return nil, err
- }
- request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
- request.Header.Set("Cookie", cookie)
- request.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36")
- //request.Header.Set("Host", "chengdu.ouchn.cn")
- client := http.Client{}
- resp, err := client.Do(request)
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
- respBytes, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return nil, err
- }
- ret := []CourseModule{}
- mos := gjson.GetBytes(respBytes, "modules").Array()
- for _, mo := range mos {
- if (len(mo.Get("syllabuses").Array())) == 0 {
- continue
- }
- item := CourseModule{}
- item.ModuleId = fmt.Sprintf("%d",mo.Get("id").Int())
- item.Name = mo.Get("name").String()
- ret = append(ret, item)
- }
- return ret, nil
- }
- type ModuleSubInfo struct {
- Name string
- Id string
- }
- type ModuleInfo struct {
- TxtInfos []ModuleSubInfo
- ExamInfos []ModuleSubInfo
- VedioInfos []ModuleSubInfo
- }
- func GetModuleInfo(courseId string, moduleId string, cookie string) (*ModuleInfo, error) {
- url := fmt.Sprintf("https://lms.ouchn.cn/api/course/%s"+
- "/all-activities?module_ids=[%s]"+
- "&activity_types=learning_activities,exams,classrooms,"+
- "live_records,rollcalls&no-loading-animation=true", courseId, moduleId)
- request, err := http.NewRequest("GET", url, nil)
- if err != nil {
- return nil, err
- }
- request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
- request.Header.Set("Cookie", cookie)
- request.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36")
- //request.Header.Set("Host", "chengdu.ouchn.cn")
- client := http.Client{}
- resp, err := client.Do(request)
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
- respBytes, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return nil, err
- }
- ret := &ModuleInfo{}
- // 试题
- exams := []ModuleSubInfo{}
- examsArray := gjson.GetBytes(respBytes, "exams").Array()
- for _, v := range examsArray {
- item := ModuleSubInfo{}
- item.Name = v.Get("title").String()
- unikey := v.Get("unique_key").String()
- array := strings.Split(unikey, "-")
- if len(array) < 2 {
- continue
- }
- item.Id = array[1]
- exams = append(exams, item)
- }
- // 文档和视频
- texts := []ModuleSubInfo{}
- vedios := []ModuleSubInfo{}
- array := gjson.GetBytes(respBytes, "learning_activities").Array()
- for _, v := range array {
- stype := v.Get("type").String()
- item := ModuleSubInfo{}
- item.Name = v.Get("title").String()
- unikey := v.Get("unique_key").String()
- array := strings.Split(unikey, "-")
- if len(array) < 2 {
- continue
- }
- item.Id = array[1]
- if stype == "page" {
- texts = append(texts, item)
- } else if stype == "online_video" {
- vedios = append(vedios, item)
- }
- }
- ret.ExamInfos = exams
- ret.TxtInfos = texts
- ret.VedioInfos = vedios
- return ret, nil
- }
- func MakeTxtUrl(courseId string, moduleId string, id string) string {
- return fmt.Sprintf("https://lms.ouchn.cn/course/%s/learning-activity/full-screen#/%s", courseId, id)
- }
- func MakeExamUrl(courseId string, moduleId string, id string) string {
- return fmt.Sprintf("https://lms.ouchn.cn/course/%s/learning-activity/full-screen#/exam/%s", courseId, id)
- }
- func VedioCompleteHandle(cookie string, id string)(error) {
- count := 0
- start, end := int64(0), int64(1000)
- for count < 5 {
- finish, err := VedioComplete(cookie, id, start, end)
- if err != nil {
- return err
- }
- if finish < 100 {
- start = end
- end += 1000
- count++
- continue
- }
- return nil
- }
- return errors.New("视频处理失败")
- }
- func VedioComplete(cookie string, id string, start, end int64) (int64, error) {
- url := fmt.Sprintf("https://lms.ouchn.cn/api/course/activities-read/%s", id)
- //fmt.Printf("get sections:%v,%v\n", str, cookie)
- m := map[string]interface{}{
- "start":start,
- "end":end,
- }
- content, _ := json.Marshal(m)
- reader := bytes.NewReader(content)
- fmt.Printf("post data:%s\n", content)
- request, err := http.NewRequest("POST", url, reader)
- if err != nil {
- return 0, err
- }
- request.Header.Set("Content-Type", "application/json")
- request.Header.Set("Cookie", cookie)
- request.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36")
- client := http.Client{}
- resp, err := client.Do(request)
- if err != nil {
- return 0, err
- }
- defer resp.Body.Close()
- respBytes, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return 0, err
- }
- //fmt.Printf("get bytes:%s\n", respBytes)
- if gjson.GetBytes(respBytes, "activity_id").Int() == 0 {
- return 0, errors.New("视频处理失败")
- }
- return gjson.GetBytes(respBytes, "data").Get("completeness").Int(), nil
- }
- func examHandleJump(wd selenium.WebDriver, courseId, moduleId, id string) error {
- url := MakeExamUrl(courseId, moduleId, id)
- wd.Get(url)
- time.Sleep(2*time.Second)
- return nil
- }
- func examHandleStart(wd selenium.WebDriver) error {
- // 点击答题按钮
- button, err := wd.FindElement(selenium.ByXPATH, "//a[@class='button button-green take-exam ng-scope']")
- if err != nil {
- return err
- }
- button.Click()
- time.Sleep(1*time.Second)
- active, _ := wd.ActiveElement()
- // 勾选同意框
- chbox, _ := active.FindElement(selenium.ByXPATH, "//input[@type='checkbox' and @name='confirm']")
- chbox.Click()
- time.Sleep(1*time.Second)
- // 点击答题
- button, _ = active.FindElement(selenium.ByXPATH, "//button[text()='开始答题' or text()='继续答题']")
- button.Click()
- time.Sleep(5*time.Second)
- return nil
- }
- func examHandleQuestion(wd selenium.WebDriver) ([]QuestionInfo, error) {
- questionClasses,_ := wd.FindElements(selenium.ByXPATH, "//li[@class='subject ng-scope text']")
- ret := []QuestionInfo{}
- for _, v := range questionClasses {
- p, err := v.FindElement(selenium.ByXPATH, "./div/div/div/span/p[@class='ng-scope']")
- if err != nil {
- return nil, err
- }
- txt, _ := p.Text()
- fmt.Printf("题类%s\n", txt)
- className := ""
- tag := 0
- // 题目类型
- if strings.Contains(txt, "选择") {
- className = "subject ng-scope single_selection"
- tag = 1
- } else if strings.Contains(txt, "判断") {
- className = "subject ng-scope true_or_false"
- tag = 2
- }
- if className == "" {
- continue
- }
- p = v
- path := fmt.Sprintf("./following-sibling::li[@class='%s']", className)
- for {
- item := QuestionInfo{Tag:tag}
- // 题目
- p, err = p.FindElement(selenium.ByXPATH, path)
- if err != nil {
- fmt.Printf("err:%v\n", err)
- break
- }
- x, err := p.FindElement(selenium.ByXPATH, "./div/div/div/span/p[@class='ng-scope']")
- if err != nil {
- break
- }
- txt, _ := x.Text()
- // 题目描述
- item.Text = txt
- // 题目选项
- ol, _ := p.FindElement(selenium.ByXPATH, "./div/div/ol")
- lis, _ := ol.FindElements(selenium.ByXPATH, "./li")
- for _, li := range lis {
- radio, err := li.FindElement(selenium.ByXPATH, "./label/span/input")
- if err != nil {
- break
- }
- answerIterm := AnswerInfo{Radio:&RadioInfo{Radio:radio}}
- if className == "subject ng-scope true_or_false" {
- answer, err := li.FindElement(selenium.ByXPATH, "./label/div/span")
- if err != nil {
- break
- }
- txt, _ := answer.Text()
- answerIterm.Text = txt
- } else {
- answer,err := li.FindElement(selenium.ByXPATH, "./label/div/span/p")
- if err != nil {
- break
- }
- txt, _ := answer.Text()
- answerIterm.Text = txt
- }
- item.AnswerArray = append(item.AnswerArray, &answerIterm)
- }
- ret = append(ret, item)
- }
- }
- return ret, nil
- }
- func examHandleMatch(questions []QuestionInfo, m map[string][]string) error {
- return chooseAnswer(questions, m)
- }
- func examHandleSubmit(wd selenium.WebDriver) error {
- // 交卷
- button1,err := wd.FindElement(selenium.ByXPATH, "//a[@class='button button-green ng-scope' and text()='交卷']")
- if err != nil {
- return err
- }
- button1.Click()
- time.Sleep(2*time.Second)
- // 弹窗中的确定
- active, _ := wd.ActiveElement()
- button2s, err := active.FindElements(selenium.ByXPATH, "//button[text()='确定']")
- if err != nil {
- return err
- }
- for _, button2 := range button2s {
- txt, _ := button2.Text()
- if txt == "确定" {
- button2.Click()
- break
- }
- }
- return errors.New("交卷未找到确定按钮")
- }
- func examHandle(wd selenium.WebDriver, courseId, moduleId, id string, qustionM map[string][]string) error {
- // 跳转页面
- if err := examHandleJump(wd, courseId, moduleId, id); err != nil {
- return err
- }
- // 点击答题按钮
- if err := examHandleStart(wd); err != nil {
- return err
- }
- // 收集题目和答案选项
- questions, err := examHandleQuestion(wd)
- if err != nil {
- return err
- }
- // 匹配题库并选择答案
- if err := examHandleMatch(questions, qustionM); err != nil {
- return err
- }
- // 提交试卷
- return examHandleSubmit(wd)
- }
- func CourseHandle(wd selenium.WebDriver, username string) error {
- title, err := wd.Title()
- if title == "" {
- return nil
- }
- array := strings.Split(title, "-")
- title = array[0]
- title = strings.TrimSpace(title)
- if !checkCourseExist(config.Conf.Courses, title) {
- fmt.Println("不执行课程:", title)
- time.Sleep(3)
- return nil
- }
- cookie, err := getCookies(wd)
- if err != nil {
- return err
- }
- defer func() {
- if strings.Contains(title, "习近平新时代中国特色社会主义思想") {
- panic("over")
- }
- }()
- fmt.Printf("***************正在处理%s课程%s\n", username, title)
- questionM, err := LoadXlsx(fmt.Sprintf("%s.xlsx", title))
- if err != nil {
- return err
- }
- // 获取课程id
- src, _ := wd.CurrentURL()
- courseId := getCourseId(src)
- if courseId == "" {
- return errors.New("课程id获取失败")
- }
- fmt.Printf("课程id:%s\n", courseId)
- // 获取课程所有栏目
- modules, err := getCourseModules(courseId, cookie)
- if err != nil {
- return errors.New(fmt.Sprintf("获取module信息失败:%s", err.Error()))
- }
- for _, module := range modules {
- fmt.Printf("***课程:%s 栏目:%s\n", title, module.Name)
- // 获取某栏目下的试题和视频数据
- moduleInfo, err := GetModuleInfo(courseId, module.ModuleId, cookie)
- if err != nil {
- return errors.New(fmt.Sprintf("获取module(%s)详细信息失败:%s", module.Name, err.Error()))
- }
- // 处理网页数据
- if true {
- for _, info := range moduleInfo.TxtInfos {
- fmt.Printf("*****正在处理网页数据:%s\n", info.Name)
- url := MakeTxtUrl(courseId, module.ModuleId, info.Id)
- wd.Get(url)
- time.Sleep(1*time.Second)
- }
- }
- if true {
- // 处理视频数据
- for _, info := range moduleInfo.VedioInfos {
- fmt.Printf("*****正在处理视频数据:%s\n", info.Name)
- err := VedioCompleteHandle(cookie, info.Id)
- if err != nil {
- fmt.Printf(" 视频%s处理失败(%s)\n", info.Name, err.Error())
- }
- time.Sleep(1*time.Second)
- }
- }
- if true {
- // 处理试题数据
- for _, info := range moduleInfo.ExamInfos {
- fmt.Printf("*****正在处理试题数据:%s\n", info.Name)
- err := examHandle(wd, courseId, module.ModuleId, info.Id, questionM)
- if err != nil {
- fmt.Printf(" 试题%s处理失败(%s)\n", info.Name, err.Error())
- }
- time.Sleep(1*time.Second)
- }
- }
- }
- return nil
- }
|