2021-11-12 07:46:33 +00:00
|
|
|
|
package lib
|
|
|
|
|
|
|
|
|
|
import (
|
2022-08-01 09:51:45 +00:00
|
|
|
|
"encoding/base64"
|
|
|
|
|
"encoding/json"
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
2021-11-12 07:46:33 +00:00
|
|
|
|
rand2 "math/rand"
|
2022-08-01 09:51:45 +00:00
|
|
|
|
"net/http"
|
2021-11-12 07:46:33 +00:00
|
|
|
|
"regexp"
|
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
|
2022-08-01 09:51:45 +00:00
|
|
|
|
"github.com/imroc/req/v3"
|
2021-11-12 07:46:33 +00:00
|
|
|
|
"github.com/mxschmitt/playwright-go"
|
|
|
|
|
log "github.com/sirupsen/logrus"
|
2022-08-01 09:51:45 +00:00
|
|
|
|
"github.com/tidwall/gjson"
|
2022-03-17 15:11:43 +00:00
|
|
|
|
|
2022-08-03 10:04:52 +00:00
|
|
|
|
"github.com/johlanse/study_xxqg/conf"
|
|
|
|
|
"github.com/johlanse/study_xxqg/model"
|
2021-11-12 07:46:33 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
MyPointsUri = "https://pc.xuexi.cn/points/my-points.html"
|
|
|
|
|
|
|
|
|
|
DailyBUTTON = `#app > div > div.layout-body > div >
|
|
|
|
|
div.my-points-section > div.my-points-content > div:nth-child(5) > div.my-points-card-footer > div.buttonbox > div`
|
2022-05-24 13:36:35 +00:00
|
|
|
|
WEEKEND = `#app > div > div.layout-body > div > div.my-points-section > div.my-points-content >
|
|
|
|
|
div:nth-child(7) > div.my-points-card-footer > div.buttonbox > div`
|
2021-11-12 07:46:33 +00:00
|
|
|
|
SPECIALBUTTON = `#app > div > div.layout-body >
|
2022-05-24 13:36:35 +00:00
|
|
|
|
div > div.my-points-section > div.my-points-content > div:nth-child(6) > div.my-points-card-footer > div.buttonbox > div`
|
2021-11-12 07:46:33 +00:00
|
|
|
|
)
|
|
|
|
|
|
2022-08-01 09:51:45 +00:00
|
|
|
|
// RespondDaily
|
|
|
|
|
/* @Description:
|
|
|
|
|
* @receiver c
|
|
|
|
|
* @param user
|
|
|
|
|
* @param model
|
|
|
|
|
*/
|
2022-03-17 15:11:43 +00:00
|
|
|
|
func (c *Core) RespondDaily(user *model.User, model string) {
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 捕获所有异常,防止程序崩溃
|
2021-11-12 07:46:33 +00:00
|
|
|
|
defer func() {
|
|
|
|
|
err := recover()
|
|
|
|
|
if err != nil {
|
2021-11-27 08:24:24 +00:00
|
|
|
|
log.Errorln("答题模块异常结束或答题已完成")
|
2021-11-29 14:44:28 +00:00
|
|
|
|
c.Push("text", "答题模块异常退出或答题已完成")
|
2021-11-22 12:07:55 +00:00
|
|
|
|
log.Errorln(err)
|
2021-11-12 07:46:33 +00:00
|
|
|
|
}
|
|
|
|
|
}()
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 判断浏览器是否被退出
|
2021-11-29 14:44:28 +00:00
|
|
|
|
if c.IsQuit() {
|
|
|
|
|
return
|
|
|
|
|
}
|
2021-11-12 07:46:33 +00:00
|
|
|
|
// 获取用户成绩
|
2022-03-17 15:11:43 +00:00
|
|
|
|
score, err := GetUserScore(user.ToCookies())
|
2021-11-12 07:46:33 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("获取分数失败,停止每日答题", err.Error())
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 创建浏览器上下文对象
|
2022-07-30 10:55:00 +00:00
|
|
|
|
context, err := c.browser.NewContext()
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 添加一个script,防止被检测
|
2022-07-30 10:55:00 +00:00
|
|
|
|
_ = context.AddInitScript(playwright.BrowserContextAddInitScriptOptions{
|
|
|
|
|
Script: playwright.String("Object.defineProperties(navigator, {webdriver:{get:()=>undefined}});")})
|
2021-11-12 07:46:33 +00:00
|
|
|
|
if err != nil {
|
2022-07-30 10:55:00 +00:00
|
|
|
|
log.Errorln("创建实例对象错误" + err.Error())
|
|
|
|
|
return
|
|
|
|
|
}
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 在退出方法时关闭对象
|
2022-07-30 10:55:00 +00:00
|
|
|
|
defer func(context playwright.BrowserContext) {
|
|
|
|
|
err := context.Close()
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("错误的关闭了实例对象" + err.Error())
|
|
|
|
|
}
|
|
|
|
|
}(context)
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 创建一个页面
|
2022-07-30 10:55:00 +00:00
|
|
|
|
page, err := context.NewPage()
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("创建页面失败" + err.Error())
|
2021-11-12 07:46:33 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 退出时关闭页面
|
2022-03-10 06:33:05 +00:00
|
|
|
|
defer func() {
|
|
|
|
|
page.Close()
|
|
|
|
|
}()
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 添加用户的cookie
|
2022-07-30 10:55:00 +00:00
|
|
|
|
err = context.AddCookies(user.ToBrowserCookies()...)
|
2021-11-12 07:46:33 +00:00
|
|
|
|
if err != nil {
|
2022-07-30 10:55:00 +00:00
|
|
|
|
log.Errorln("添加cookie失败" + err.Error())
|
2021-11-12 07:46:33 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 跳转到积分页面
|
2021-11-12 07:46:33 +00:00
|
|
|
|
_, err = page.Goto(MyPointsUri, playwright.PageGotoOptions{
|
|
|
|
|
Referer: playwright.String(MyPointsUri),
|
2022-02-21 13:55:41 +00:00
|
|
|
|
Timeout: playwright.Float(10000),
|
2021-11-12 07:46:33 +00:00
|
|
|
|
WaitUntil: playwright.WaitUntilStateDomcontentloaded,
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
2022-05-27 13:37:16 +00:00
|
|
|
|
log.Errorln("跳转页面失败" + err.Error())
|
2021-11-12 07:46:33 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
2022-08-02 01:32:15 +00:00
|
|
|
|
log.Infoln("已加载答题模块")
|
|
|
|
|
// 判断答题类型,然后相应处理
|
2021-11-12 07:46:33 +00:00
|
|
|
|
switch model {
|
|
|
|
|
case "daily":
|
|
|
|
|
{
|
|
|
|
|
// 检测是否已经完成
|
|
|
|
|
if score.Content["daily"].CurrentScore >= score.Content["daily"].MaxScore {
|
|
|
|
|
log.Infoln("检测到每日答题已经完成,即将退出答题")
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 点击每日答题的按钮
|
2021-11-12 07:46:33 +00:00
|
|
|
|
err = page.Click(DailyBUTTON)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("跳转到积分页面错误")
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
2021-11-29 14:44:28 +00:00
|
|
|
|
c.Push("text", "已加载每日答题模块")
|
2021-11-12 07:46:33 +00:00
|
|
|
|
}
|
|
|
|
|
case "weekly":
|
|
|
|
|
{
|
|
|
|
|
// 检测是否已经完成
|
|
|
|
|
if score.Content["weekly"].CurrentScore >= score.Content["weekly"].MaxScore {
|
|
|
|
|
log.Infoln("检测到每周答题已经完成,即将退出答题")
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
2022-08-01 09:51:45 +00:00
|
|
|
|
// err = page.Click(WEEKEND)
|
|
|
|
|
// if err != nil {
|
|
|
|
|
// log.Errorln("跳转到积分页面错误")
|
|
|
|
|
// return
|
|
|
|
|
//}
|
2022-08-02 01:32:15 +00:00
|
|
|
|
|
|
|
|
|
// 获取每周答题的ID
|
2022-08-01 09:51:45 +00:00
|
|
|
|
id, err := getweekID(user.ToCookies())
|
2021-11-12 07:46:33 +00:00
|
|
|
|
if err != nil {
|
2022-08-01 09:51:45 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 跳转到每周答题界面
|
2022-08-01 09:51:45 +00:00
|
|
|
|
_, err = page.Goto(fmt.Sprintf("https://pc.xuexi.cn/points/exam-weekly-detail.html?id=%d", id), playwright.PageGotoOptions{
|
|
|
|
|
Referer: playwright.String(MyPointsUri),
|
|
|
|
|
Timeout: playwright.Float(10000),
|
|
|
|
|
WaitUntil: playwright.WaitUntilStateDomcontentloaded,
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("跳转到答题页面错误" + err.Error())
|
2021-11-12 07:46:33 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
2021-11-29 14:44:28 +00:00
|
|
|
|
c.Push("text", "已加载每周答题模块")
|
2021-11-12 07:46:33 +00:00
|
|
|
|
}
|
|
|
|
|
case "special":
|
|
|
|
|
{
|
|
|
|
|
// 检测是否已经完成
|
|
|
|
|
if score.Content["special"].CurrentScore >= score.Content["special"].MaxScore {
|
|
|
|
|
log.Infoln("检测到特殊答题已经完成,即将退出答题")
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
2022-08-01 09:51:45 +00:00
|
|
|
|
// err = page.Click(SPECIALBUTTON)
|
|
|
|
|
// if err != nil {
|
|
|
|
|
// log.Errorln("跳转到积分页面错误")
|
|
|
|
|
//
|
|
|
|
|
// return
|
|
|
|
|
//}
|
2022-08-02 01:32:15 +00:00
|
|
|
|
|
|
|
|
|
// 获取专项答题ID
|
2022-08-01 09:51:45 +00:00
|
|
|
|
id, err := getSpecialID(user.ToCookies())
|
2021-11-12 07:46:33 +00:00
|
|
|
|
if err != nil {
|
2022-08-01 09:51:45 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 跳转到专项答题界面
|
2022-08-01 09:51:45 +00:00
|
|
|
|
_, err = page.Goto(fmt.Sprintf("https://pc.xuexi.cn/points/exam-paper-detail.html?id=%d", id), playwright.PageGotoOptions{
|
|
|
|
|
Referer: playwright.String(MyPointsUri),
|
|
|
|
|
Timeout: playwright.Float(10000),
|
|
|
|
|
WaitUntil: playwright.WaitUntilStateDomcontentloaded,
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("跳转到答题页面错误" + err.Error())
|
2021-11-12 07:46:33 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
2021-11-29 14:44:28 +00:00
|
|
|
|
c.Push("text", "已加载专项答题模块")
|
2021-11-12 07:46:33 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
time.Sleep(5 * time.Second)
|
2021-12-06 05:31:05 +00:00
|
|
|
|
// 跳转到答题页面,若返回true则说明已答完
|
2022-08-01 09:51:45 +00:00
|
|
|
|
// if getAnswerPage(page, model) {
|
|
|
|
|
// return
|
|
|
|
|
//}
|
2021-11-12 07:46:33 +00:00
|
|
|
|
|
2021-12-07 10:27:48 +00:00
|
|
|
|
tryCount := 0
|
2021-11-12 07:46:33 +00:00
|
|
|
|
for true {
|
2021-12-07 10:27:48 +00:00
|
|
|
|
label:
|
|
|
|
|
tryCount++
|
|
|
|
|
if tryCount >= 30 {
|
|
|
|
|
log.Panicln("多次循环尝试答题,已超出30次,自动退出")
|
|
|
|
|
}
|
2021-11-29 14:44:28 +00:00
|
|
|
|
if c.IsQuit() {
|
|
|
|
|
return
|
|
|
|
|
}
|
2021-11-12 07:46:33 +00:00
|
|
|
|
// 查看是否存在答题按钮,若按钮可用则重新提交答题
|
|
|
|
|
btn, err := page.QuerySelector(`#app > div > div.layout-body > div > div.detail-body > div.action-row > button`)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Infoln("获取提交按钮失败,本次答题结束" + err.Error())
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enabled, err := btn.IsEnabled()
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln(err.Error())
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if enabled {
|
|
|
|
|
err := btn.Click()
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("提交答案失败")
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 该元素存在则说明出现了滑块
|
2022-03-06 14:03:14 +00:00
|
|
|
|
handle, _ := page.QuerySelector("#nc_mask > div")
|
|
|
|
|
if handle != nil {
|
|
|
|
|
log.Infoln(handle)
|
|
|
|
|
en, err := handle.IsVisible()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if en {
|
2022-03-10 06:33:05 +00:00
|
|
|
|
page.Mouse().Move(496, 422)
|
|
|
|
|
time.Sleep(1 * time.Second)
|
|
|
|
|
page.Mouse().Down()
|
|
|
|
|
|
|
|
|
|
page.Mouse().Move(772, 416, playwright.MouseMoveOptions{})
|
|
|
|
|
page.Mouse().Up()
|
|
|
|
|
time.Sleep(10 * time.Second)
|
2022-03-06 14:03:14 +00:00
|
|
|
|
log.Infoln("可能存在滑块")
|
2022-03-10 06:33:05 +00:00
|
|
|
|
c.Push("text", "答题过程出现滑块,正在尝试滑动")
|
2022-03-17 15:11:43 +00:00
|
|
|
|
en, err = handle.IsVisible()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if en {
|
|
|
|
|
page.Evaluate("__nc.reset()")
|
|
|
|
|
goto label
|
|
|
|
|
}
|
2022-03-06 14:03:14 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-11-12 07:46:33 +00:00
|
|
|
|
switch model {
|
|
|
|
|
case "daily":
|
|
|
|
|
{
|
|
|
|
|
// 检测是否已经完成
|
|
|
|
|
if score.Content["daily"].CurrentScore >= score.Content["daily"].MaxScore {
|
|
|
|
|
log.Infoln("检测到每日答题已经完成,即将退出答题")
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
case "weekly":
|
|
|
|
|
{
|
|
|
|
|
// 检测是否已经完成
|
|
|
|
|
if score.Content["weekly"].CurrentScore >= score.Content["weekly"].MaxScore {
|
|
|
|
|
log.Infoln("检测到每周答题已经完成,即将退出答题")
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
case "special":
|
|
|
|
|
{
|
|
|
|
|
// 检测是否已经完成
|
|
|
|
|
if score.Content["special"].CurrentScore >= score.Content["special"].MaxScore {
|
|
|
|
|
log.Infoln("检测到特殊答题已经完成,即将退出答题")
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取题目类型
|
|
|
|
|
category, err := page.QuerySelector(
|
|
|
|
|
`#app > div > div.layout-body > div > div.detail-body > div.question > div.q-header`)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("没有找到题目元素" + err.Error())
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
2021-11-27 08:24:24 +00:00
|
|
|
|
_ = category.WaitForElementState(`visible`)
|
2021-11-12 07:46:33 +00:00
|
|
|
|
time.Sleep(1 * time.Second)
|
|
|
|
|
|
|
|
|
|
// 获取题目
|
|
|
|
|
question, err := page.QuerySelector(
|
|
|
|
|
`#app > div > div.layout-body > div > div.detail-body > div.question > div.q-body > div`)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("未找到题目问题元素")
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 获取题目类型
|
2021-11-12 07:46:33 +00:00
|
|
|
|
categoryText, err := category.TextContent()
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("获取题目元素失败" + err.Error())
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
log.Infoln("## 题目类型:" + categoryText)
|
|
|
|
|
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 获取题目的问题
|
2021-11-12 07:46:33 +00:00
|
|
|
|
questionText, err := question.TextContent()
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("获取题目问题失败" + err.Error())
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
log.Infoln("## 题目:" + questionText)
|
|
|
|
|
|
|
|
|
|
// 获取答题帮助
|
|
|
|
|
openTips, err := page.QuerySelector(
|
|
|
|
|
`#app > div > div.layout-body > div > div.detail-body > div.question > div.q-footer > span`)
|
2021-12-07 10:27:48 +00:00
|
|
|
|
if err != nil || openTips == nil {
|
|
|
|
|
log.Errorln("未获取到题目提示信息")
|
2021-11-12 07:46:33 +00:00
|
|
|
|
|
2021-12-07 10:27:48 +00:00
|
|
|
|
goto label
|
2021-11-12 07:46:33 +00:00
|
|
|
|
}
|
2021-12-07 10:27:48 +00:00
|
|
|
|
log.Debugln("开始尝试获取打开提示信息按钮")
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 点击提示的按钮
|
2021-11-12 07:46:33 +00:00
|
|
|
|
err = openTips.Click()
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("点击打开提示信息按钮失败" + err.Error())
|
2021-12-07 10:27:48 +00:00
|
|
|
|
goto label
|
2021-11-12 07:46:33 +00:00
|
|
|
|
}
|
2021-12-07 10:27:48 +00:00
|
|
|
|
log.Debugln("已打开提示信息")
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 获取页面内容
|
2021-11-12 07:46:33 +00:00
|
|
|
|
content, err := page.Content()
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("获取网页全体内容失败" + err.Error())
|
2021-12-07 10:27:48 +00:00
|
|
|
|
goto label
|
2021-11-12 07:46:33 +00:00
|
|
|
|
}
|
2022-04-24 08:55:39 +00:00
|
|
|
|
time.Sleep(time.Second * time.Duration(rand2.Intn(3)))
|
2021-12-07 10:27:48 +00:00
|
|
|
|
log.Debugln("以获取网页内容")
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 关闭提示信息
|
2021-11-12 07:46:33 +00:00
|
|
|
|
err = openTips.Click()
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("点击打开提示信息按钮失败" + err.Error())
|
|
|
|
|
|
2021-12-07 10:27:48 +00:00
|
|
|
|
goto label
|
2021-11-12 07:46:33 +00:00
|
|
|
|
}
|
2021-12-07 10:27:48 +00:00
|
|
|
|
log.Debugln("已关闭提示信息")
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 从整个页面内容获取提示信息
|
2021-11-12 07:46:33 +00:00
|
|
|
|
tips := getTips(content)
|
|
|
|
|
log.Infoln("[提示信息]:", tips)
|
|
|
|
|
// 填空题
|
|
|
|
|
switch {
|
|
|
|
|
case strings.Contains(categoryText, "填空题"):
|
2022-02-14 09:57:55 +00:00
|
|
|
|
if len(tips) < 1 {
|
|
|
|
|
tips = append(tips, "不知道")
|
|
|
|
|
}
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 填充填空题
|
2021-11-12 07:46:33 +00:00
|
|
|
|
err := FillBlank(page, tips)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("填空题答题失败" + err.Error())
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
case strings.Contains(categoryText, "多选题"):
|
|
|
|
|
log.Infoln("读取到多选题")
|
|
|
|
|
options, err := getOptions(page)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("获取选项失败" + err.Error())
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
log.Infoln("获取到选项答案:", options)
|
|
|
|
|
log.Infoln("[多选题选项]:", options)
|
|
|
|
|
var answer []string
|
2021-12-06 05:49:03 +00:00
|
|
|
|
|
|
|
|
|
for _, option := range options {
|
|
|
|
|
for _, tip := range tips {
|
|
|
|
|
if strings.Contains(option, tip) {
|
|
|
|
|
answer = append(answer, option)
|
2021-11-12 07:46:33 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-12-06 05:49:03 +00:00
|
|
|
|
|
|
|
|
|
if len(answer) < 1 {
|
|
|
|
|
answer = append(answer, options...)
|
|
|
|
|
log.Infoln("无法判断答案,自动选择ABCD")
|
|
|
|
|
}
|
2021-12-02 12:44:22 +00:00
|
|
|
|
log.Infoln("根据提示分别选择了", RemoveRepByLoop(answer))
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 多选题选择
|
2021-11-12 07:46:33 +00:00
|
|
|
|
err = radioCheck(page, answer)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
case strings.Contains(categoryText, "单选题"):
|
|
|
|
|
log.Infoln("读取到单选题")
|
|
|
|
|
options, err := getOptions(page)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("获取选项失败" + err.Error())
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
log.Infoln("获取到选项答案:", options)
|
2021-11-24 14:05:37 +00:00
|
|
|
|
|
2021-11-12 07:46:33 +00:00
|
|
|
|
var answer []string
|
2021-12-06 05:49:03 +00:00
|
|
|
|
|
|
|
|
|
for _, option := range options {
|
|
|
|
|
for _, tip := range tips {
|
|
|
|
|
if strings.Contains(option, tip) {
|
|
|
|
|
answer = append(answer, option)
|
2021-11-12 07:46:33 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-12-06 05:49:03 +00:00
|
|
|
|
if len(answer) < 1 {
|
|
|
|
|
answer = append(answer, options[0])
|
|
|
|
|
log.Infoln("无法判断答案,自动选择A")
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-24 14:05:37 +00:00
|
|
|
|
log.Infoln("根据提示分别选择了", answer)
|
2021-11-12 07:46:33 +00:00
|
|
|
|
err = radioCheck(page, answer)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-03-17 15:11:43 +00:00
|
|
|
|
score, _ = GetUserScore(user.ToCookies())
|
2021-11-12 07:46:33 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-06 05:31:05 +00:00
|
|
|
|
func getAnswerPage(page playwright.Page, model string) bool {
|
2021-11-12 07:46:33 +00:00
|
|
|
|
selectPages, err := page.QuerySelectorAll(`#app .ant-pagination .ant-pagination-item`)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("获取到页码失败")
|
|
|
|
|
|
2021-12-06 05:31:05 +00:00
|
|
|
|
return false
|
2021-11-12 07:46:33 +00:00
|
|
|
|
}
|
|
|
|
|
log.Infoln("共获取到", len(selectPages), "页")
|
|
|
|
|
modelName := ""
|
|
|
|
|
modelSlector := ""
|
|
|
|
|
switch model {
|
|
|
|
|
case "daily":
|
2021-12-06 05:31:05 +00:00
|
|
|
|
return false
|
2021-11-12 07:46:33 +00:00
|
|
|
|
case "weekly":
|
|
|
|
|
modelName = "每周答题"
|
|
|
|
|
modelSlector = "button.ant-btn-primary"
|
|
|
|
|
case "special":
|
|
|
|
|
modelName = "专项答题"
|
|
|
|
|
modelSlector = "#app .items .item button"
|
|
|
|
|
}
|
|
|
|
|
for i := 1; i <= len(selectPages); i++ {
|
|
|
|
|
log.Infoln("获取到"+modelName, "第", i, "页")
|
|
|
|
|
err1 := selectPages[i-1].Click()
|
|
|
|
|
if err1 != nil {
|
|
|
|
|
log.Errorln("点击页码失败")
|
|
|
|
|
}
|
2022-02-24 06:15:12 +00:00
|
|
|
|
time.Sleep(2 * time.Second)
|
2021-11-12 07:46:33 +00:00
|
|
|
|
datas, err := page.QuerySelectorAll(modelSlector)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("获取页面内容失败")
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
for _, data := range datas {
|
|
|
|
|
content, err := data.TextContent()
|
|
|
|
|
if err != nil {
|
2022-02-24 06:15:12 +00:00
|
|
|
|
log.Errorln("获取按钮文本失败" + err.Error())
|
2021-11-12 07:46:33 +00:00
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if strings.Contains(content, "重新") || strings.Contains(content, "满分") {
|
|
|
|
|
continue
|
|
|
|
|
} else {
|
|
|
|
|
if strings.Contains(content, "电影试题") {
|
|
|
|
|
log.Infoln("发现有未答题的电影试题")
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
enabled, err := data.IsEnabled()
|
|
|
|
|
if err != nil {
|
2021-12-06 05:31:05 +00:00
|
|
|
|
return false
|
2021-11-12 07:46:33 +00:00
|
|
|
|
}
|
|
|
|
|
if enabled {
|
|
|
|
|
log.Infoln("按钮可用")
|
|
|
|
|
}
|
2022-02-24 06:15:12 +00:00
|
|
|
|
data.WaitForElementState("stable", playwright.ElementHandleWaitForElementStateOptions{Timeout: playwright.Float(10000)})
|
|
|
|
|
time.Sleep(5 * time.Second)
|
2021-11-12 07:46:33 +00:00
|
|
|
|
err = data.Click(playwright.ElementHandleClickOptions{
|
|
|
|
|
Button: nil,
|
|
|
|
|
ClickCount: playwright.Int(2),
|
|
|
|
|
Delay: nil,
|
|
|
|
|
Force: nil,
|
|
|
|
|
Modifiers: nil,
|
|
|
|
|
NoWaitAfter: nil,
|
|
|
|
|
Position: nil,
|
|
|
|
|
Timeout: playwright.Float(100000),
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("点击按钮失败" + err.Error())
|
|
|
|
|
time.Sleep(2 * time.Second)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
time.Sleep(3 * time.Second)
|
2021-12-06 05:31:05 +00:00
|
|
|
|
return false
|
2021-11-12 07:46:33 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-12-06 05:31:05 +00:00
|
|
|
|
log.Infoln("检测到每周答题已经完成")
|
|
|
|
|
return true
|
2021-11-12 07:46:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func radioCheck(page playwright.Page, answer []string) error {
|
|
|
|
|
radios, err := page.QuerySelectorAll(`.q-answer.choosable`)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("获取选项失败")
|
|
|
|
|
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
log.Debugln("获取到", len(radios), "个按钮")
|
|
|
|
|
for _, radio := range radios {
|
|
|
|
|
textContent, err := radio.TextContent()
|
|
|
|
|
if err != nil {
|
2022-07-26 10:30:01 +00:00
|
|
|
|
log.Errorln("获取选项答案文本出现错误" + err.Error())
|
2021-11-12 07:46:33 +00:00
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
for _, s := range answer {
|
|
|
|
|
if textContent == s {
|
|
|
|
|
err := radio.Click()
|
|
|
|
|
if err != nil {
|
2022-07-26 10:30:01 +00:00
|
|
|
|
log.Errorln("点击选项出现错误" + err.Error())
|
2021-11-12 07:46:33 +00:00
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
r := rand2.Intn(2)
|
|
|
|
|
time.Sleep(time.Duration(r) * time.Second)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
r := rand2.Intn(5)
|
|
|
|
|
time.Sleep(time.Duration(r) * time.Second)
|
|
|
|
|
checkNextBotton(page)
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getOptions(page playwright.Page) ([]string, error) {
|
|
|
|
|
handles, err := page.QuerySelectorAll(`.q-answer.choosable`)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("获取选项信息失败")
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
var options []string
|
|
|
|
|
for _, handle := range handles {
|
|
|
|
|
content, err := handle.TextContent()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
options = append(options, content)
|
|
|
|
|
}
|
|
|
|
|
return options, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getTips(data string) []string {
|
|
|
|
|
data = strings.ReplaceAll(data, " ", "")
|
|
|
|
|
data = strings.ReplaceAll(data, "\n", "")
|
|
|
|
|
compile := regexp.MustCompile(`<fontcolor="red">(.*?)</font>`)
|
|
|
|
|
match := compile.FindAllStringSubmatch(data, -1)
|
|
|
|
|
var tips []string
|
|
|
|
|
for _, i := range match {
|
|
|
|
|
tips = append(tips, i[1])
|
|
|
|
|
}
|
|
|
|
|
return tips
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func FillBlank(page playwright.Page, tips []string) error {
|
|
|
|
|
video := false
|
|
|
|
|
var answer []string
|
|
|
|
|
for _, tip := range tips {
|
|
|
|
|
if tip == "请观看视频" {
|
|
|
|
|
video = true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if video {
|
|
|
|
|
answer = append(answer, "不知道")
|
|
|
|
|
} else {
|
|
|
|
|
answer = tips
|
|
|
|
|
}
|
|
|
|
|
inouts, err := page.QuerySelectorAll(`div.q-body > div > input`)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("获取输入框错误" + err.Error())
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
log.Debugln("获取到", len(inouts), "个填空")
|
|
|
|
|
if len(inouts) == 1 && len(tips) > 1 {
|
|
|
|
|
temp := ""
|
|
|
|
|
for _, tip := range tips {
|
|
|
|
|
temp += tip
|
|
|
|
|
}
|
|
|
|
|
answer = strings.Split(temp, ",")
|
2022-07-26 10:25:18 +00:00
|
|
|
|
log.Infoln("答案已合并处理")
|
2021-11-12 07:46:33 +00:00
|
|
|
|
}
|
|
|
|
|
for i := 0; i < len(inouts); i++ {
|
|
|
|
|
err := inouts[i].Fill(answer[i])
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("填充答案失败" + err.Error())
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
r := rand2.Intn(5)
|
|
|
|
|
time.Sleep(time.Duration(r) * time.Second)
|
|
|
|
|
}
|
|
|
|
|
r := rand2.Intn(2)
|
|
|
|
|
time.Sleep(time.Duration(r) * time.Second)
|
|
|
|
|
checkNextBotton(page)
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func checkNextBotton(page playwright.Page) {
|
|
|
|
|
btns, err := page.QuerySelectorAll(`#app .action-row > button`)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("未检测到按钮" + err.Error())
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if len(btns) <= 1 {
|
|
|
|
|
err := btns[0].Check()
|
|
|
|
|
if err != nil {
|
2021-12-06 09:42:28 +00:00
|
|
|
|
log.Errorln("点击下一题按钮失败")
|
2021-11-12 07:46:33 +00:00
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
time.Sleep(2 * time.Second)
|
|
|
|
|
_, err = btns[0].GetAttribute("disabled")
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Infoln("未检测到禁言属性")
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
err := btns[1].Click()
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("提交试卷失败")
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
log.Infoln("已成功提交试卷")
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-12-02 12:44:22 +00:00
|
|
|
|
|
|
|
|
|
// RemoveRepByLoop 通过两重循环过滤重复元素
|
|
|
|
|
func RemoveRepByLoop(slc []string) []string {
|
|
|
|
|
var result []string // 存放结果
|
|
|
|
|
for i := range slc {
|
|
|
|
|
flag := true
|
|
|
|
|
for j := range result {
|
|
|
|
|
if slc[i] == result[j] {
|
|
|
|
|
flag = false // 存在重复元素,标识为false
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if flag { // 标识为false,不添加进结果
|
|
|
|
|
result = append(result, slc[i])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result
|
|
|
|
|
}
|
2022-08-01 09:51:45 +00:00
|
|
|
|
|
|
|
|
|
func getSpecialID(cookies []*http.Cookie) (int, error) {
|
|
|
|
|
c := req.C()
|
|
|
|
|
c.SetCommonCookies(cookies...)
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 获取专项答题列表
|
2022-08-01 09:51:45 +00:00
|
|
|
|
repo, err := c.R().SetQueryParams(map[string]string{"pageSize": "1000", "pageNo": "1"}).Get(querySpecialList)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("获取专项答题列表错误" + err.Error())
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
dataB64, err := repo.ToString()
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("获取专项答题列表获取string错误" + err.Error())
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 因为返回内容使用base64编码,所以需要对内容进行转码
|
2022-08-01 09:51:45 +00:00
|
|
|
|
data, err := base64.StdEncoding.DecodeString(gjson.Get(dataB64, "data_str").String())
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("获取专项答题列表转换b64错误" + err.Error())
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// 创建实例对象
|
2022-08-01 09:51:45 +00:00
|
|
|
|
list := new(SpecialList)
|
2022-08-02 01:32:15 +00:00
|
|
|
|
// json序列号
|
2022-08-01 09:51:45 +00:00
|
|
|
|
err = json.Unmarshal(data, list)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("获取专项答题列表转换json错误" + err.Error())
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
log.Infoln(fmt.Sprintf("共获取到专项答题%d个", list.TotalCount))
|
2022-08-02 01:32:15 +00:00
|
|
|
|
|
|
|
|
|
// 判断是否配置选题顺序,若ReverseOrder为true则从后面选题
|
|
|
|
|
if conf.GetConfig().ReverseOrder {
|
|
|
|
|
for i := len(list.List) - 1; i >= 0; i-- {
|
|
|
|
|
if list.List[i].TipScore == 0 {
|
|
|
|
|
log.Infoln(fmt.Sprintf("获取到未答专项答题: %v,id: %v", list.List[i].Name, list.List[i].Id))
|
|
|
|
|
return list.List[i].Id, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for _, s := range list.List {
|
|
|
|
|
if s.TipScore == 0 {
|
|
|
|
|
log.Infoln(fmt.Sprintf("获取到未答专项答题: %v,id: %v", s.Name, s.Id))
|
|
|
|
|
return s.Id, nil
|
|
|
|
|
}
|
2022-08-01 09:51:45 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
log.Warningln("你已不存在未答的专项答题了")
|
|
|
|
|
return 0, errors.New("未找到专项答题")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getweekID(cookies []*http.Cookie) (int, error) {
|
|
|
|
|
c := req.C()
|
|
|
|
|
c.SetCommonCookies(cookies...)
|
|
|
|
|
repo, err := c.R().SetQueryParams(map[string]string{"pageSize": "500", "pageNo": "1"}).Get(queryWeekList)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("获取每周答题列表错误" + err.Error())
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
dataB64, err := repo.ToString()
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("获取每周答题列表获取string错误" + err.Error())
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
data, err := base64.StdEncoding.DecodeString(gjson.Get(dataB64, "data_str").String())
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("获取每周答题列表转换b64错误" + err.Error())
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
list := new(WeekList)
|
|
|
|
|
err = json.Unmarshal(data, list)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("获取每周答题列表转换json错误" + err.Error())
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
log.Infoln(fmt.Sprintf("共获取到每周答题%d个", list.TotalCount))
|
2022-08-02 01:32:15 +00:00
|
|
|
|
|
|
|
|
|
if conf.GetConfig().ReverseOrder {
|
|
|
|
|
for i := len(list.List) - 1; i >= 0; i-- {
|
|
|
|
|
for _, practice := range list.List[i].Practices {
|
|
|
|
|
if practice.TipScore == 0 {
|
|
|
|
|
log.Infoln(fmt.Sprintf("获取到未答每周答题: %v,id: %v", practice.Name, practice.Id))
|
|
|
|
|
return practice.Id, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for _, s := range list.List {
|
|
|
|
|
for _, practice := range s.Practices {
|
|
|
|
|
if practice.TipScore == 0 {
|
|
|
|
|
log.Infoln(fmt.Sprintf("获取到未答每周答题: %v,id: %v", practice.Name, practice.Id))
|
|
|
|
|
return practice.Id, nil
|
|
|
|
|
}
|
2022-08-01 09:51:45 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
log.Warningln("你已不存在未答的每周答题了")
|
|
|
|
|
return 0, errors.New("未找到每周答题")
|
|
|
|
|
}
|