package main import ( "flag" "fmt" "github.com/PuerkitoBio/goquery" "io" "math/rand" "net/url" "regexp" "strconv" "strings" "sync" "time" "unicode/utf8" ) var Username = flag.String("u", "", "统一认证学号/用户名") var Password = flag.String("p", "", "统一认证密码") var evaluationChan = make(chan struct{}, 3) var waitGroup = sync.WaitGroup{} func main() { rand.Seed(time.Now().UnixNano()) flag.Parse() if *Username == "" || *Password == "" { flag.Usage() return } fmt.Println("正在登入系统...") res, err := Client.Do(createRequest("GET", "http://bkzhjx.wh.sdu.edu.cn/sso.jsp", nil)) _ = checkHttpError(res, err) casUrl := "https://pass.sdu.edu.cn/cas/login?service=http%3A%2F%2Fbkzhjx.wh.sdu.edu.cn%2Fsso.jsp" res, err = Client.Do(createRequest("GET", casUrl, nil)) err = checkHttpError(res, err) if err != nil { panic(err) } html, _ := io.ReadAll(res.Body) ticket := regexp.MustCompile("name=\"lt\" value=\"(.*?)\"").FindStringSubmatch(string(html))[1] rsa := strEnc(*Username + *Password + ticket) loginValues := url.Values{ "rsa": {rsa}, "ul": {strconv.Itoa(utf8.RuneCountInString(*Username))}, "pl": {strconv.Itoa(utf8.RuneCountInString(*Password))}, "lt": {ticket}, "execution": {"e1s1"}, "_eventId": {"submit"}, } res, err = Client.Do(createRequest("POST", casUrl, strings.NewReader(loginValues.Encode()))) err = checkHttpError(res, err) if err != nil { panic(err) } html, _ = io.ReadAll(res.Body) if !strings.Contains(string(html), "强智科技教务系统欢迎") { fmt.Println("用户名或密码错误") return } fmt.Println("登入系统成功") res, err = Client.Do(createRequest("GET", "https://bkzhjx.wh.sdu.edu.cn/jsxsd/xspj/xspj_find.do", nil)) err = checkHttpError(res, err) if err != nil { panic(err) } html, _ = io.ReadAll(res.Body) evaluationLink := "https://bkzhjx.wh.sdu.edu.cn" + regexp.MustCompile("评价").FindStringSubmatch(htmlOfTr)[1] evaluationFullURL = strings.ReplaceAll(evaluationFullURL, "&", "&") waitGroup.Add(1) go evaluateByURL(tds[2], evaluationFullURL) }) waitGroup.Wait() } func evaluateByURL(course string, fullURL string) { evaluationChan <- struct{}{} defer func() { <-evaluationChan waitGroup.Done() }() fmt.Println("正在评教:" + course) res, err := Client.Do(createRequest("GET", fullURL, nil)) err = checkHttpError(res, err) if err != nil { fmt.Printf("评教 "+course+" 出错:%+v", err) return } html, _ := io.ReadAll(res.Body) postData := url.Values{ "issubmit": {"1"}, "kctzdnd": {"3"}, "yxjspx": {"1"}, "isxtjg": {"1"}, "jynr": {"课程良好"}, } for _, key := range []string{"pj09id", "pj01id", "pj0502id", "jg0101id", "jx0404id", "xsflid", "xnxq01id", "jx02id", "pj02id", "ifypjxx", "pj03id", "pageIndex"} { addStdHiddenFormValue(string(html), &postData, key) } doc, _ := goquery.NewDocumentFromReader(strings.NewReader(string(html))) degree := 2 doc.Find("table tr").Each(func(i int, selection *goquery.Selection) { htmlOfTr, _ := selection.Html() if !strings.Contains(htmlOfTr, "pj06xh") { return } pj06ix := addStdHiddenFormValue(htmlOfTr, &postData, "pj06xh") var selectedHash string for _, item := range []int{1, 2, 3, 4, 5} { hash, _ := selection.Find("input[id=pj0601id_" + pj06ix + "_" + strconv.Itoa(item) + "]").Attr("value") currentScore, _ := selection.Find("input[name=pj0601fz_" + pj06ix + "_" + hash + "]").Attr("value") postData.Add("pj0601fz_"+pj06ix+"_"+hash, currentScore) if degree == item { selectedHash = hash } } postData.Add("pj0601id_"+pj06ix, selectedHash) if degree == 2 { degree = 1 } }) res, err = Client.Do(createRequest("POST", "https://bkzhjx.wh.sdu.edu.cn/jsxsd/xspj/xspj_save.do", strings.NewReader(postData.Encode()))) err = checkHttpError(res, err) if err != nil { fmt.Printf("评教 "+course+" 出错:%+v", err) return } html, _ = io.ReadAll(res.Body) if !strings.Contains(string(html), "成功") { fmt.Printf("评教 "+course+" 出错:%+v", err) fmt.Println(string(html)) return } } func addStdHiddenFormValue(html string, obj *url.Values, key string) string { value := regexp.MustCompile("input type=\"hidden\" name=\"" + key + "\" value=\"(.*?)\"").FindStringSubmatch(html)[1] obj.Add(key, value) return value }