From 28065f6318ed28bc4972abaca04040716d56dbb9 Mon Sep 17 00:00:00 2001 From: SchwarzSail <119314702+SchwarzSail@users.noreply.github.com> Date: Sat, 23 Nov 2024 12:22:05 +0800 Subject: [PATCH] exam room query completed (#15) * exam room query completed * fix importing --- constants/constants.go | 1 + jwch_test.go | 10 +++++++ model.go | 13 ++++++++ room.go | 68 +++++++++++++++++++++++++++++++++++++++--- 4 files changed, 88 insertions(+), 4 deletions(-) diff --git a/constants/constants.go b/constants/constants.go index 6c1b8a8..45f1c57 100644 --- a/constants/constants.go +++ b/constants/constants.go @@ -28,6 +28,7 @@ const ( CreditQueryURL = "https://jwcjwxt2.fzu.edu.cn:81/student/xyzk/xftj/CreditStatistics.aspx" GPAQueryURL = "https://jwcjwxt2.fzu.edu.cn:81/student/xyzk/jdpm/GPA_sheet.aspx" VerifyCodeURL = "https://jwcjwxt1.fzu.edu.cn/plus/verifycode.asp" + ExamRoomQueryURL = "https://jwcjwxt2.fzu.edu.cn:81/student/xkjg/examination/exam_list.aspx" JwchPrefix = "https://jwcjwxt2.fzu.edu.cn:81" JwchReferer = "https://jwcjwxt1.fzu.edu.cn/" diff --git a/jwch_test.go b/jwch_test.go index 40f7ad4..b527d01 100644 --- a/jwch_test.go +++ b/jwch_test.go @@ -267,3 +267,13 @@ func TestGetUnifiedExam(t *testing.T) { // 不允许输出考试成绩信息 } + +// 考场信息 +func TestGetExamRoomInfo(t *testing.T) { + _, err := stu.GetExamRoom(ExamRoomReq{ + Term: "202401", + }) + if err != nil { + t.Error(err) + } +} diff --git a/model.go b/model.go index 1cea0da..a75a60c 100644 --- a/model.go +++ b/model.go @@ -174,3 +174,16 @@ type UnifiedExam struct { Score string Term string } + +type ExamRoomReq struct { + Term string +} + +type ExamRoomInfo struct { + CourseName string // 课程名称 + Credit string // 学分 + Teacher string // 任课教师 + Date string // 考试日期 + Time string // 考试时间 + Location string // 考试地点 +} diff --git a/room.go b/room.go index 972df70..0f97729 100644 --- a/room.go +++ b/room.go @@ -17,6 +17,8 @@ limitations under the License. package jwch import ( + "strings" + "github.com/antchfx/htmlquery" "golang.org/x/net/html" @@ -24,7 +26,7 @@ import ( ) func (s *Student) GetEmptyRoom(req EmptyRoomReq) ([]string, error) { - viewStateMap, err := s.getEmptyRoomState() + viewStateMap, err := s.getState(constants.ClassroomQueryURL) if err != nil { return nil, err } @@ -95,7 +97,7 @@ func (s *Student) GetEmptyRoom(req EmptyRoomReq) ([]string, error) { } func (s *Student) GetQiShanEmptyRoom(req EmptyRoomReq) ([]string, error) { - viewStateMap, err := s.getEmptyRoomState() + viewStateMap, err := s.getState(constants.ClassroomQueryURL) if err != nil { return nil, err } @@ -182,8 +184,9 @@ func (s *Student) GetQiShanEmptyRoom(req EmptyRoomReq) ([]string, error) { } // 获取VIEWSTATE和EVENTVALIDATION -func (s *Student) getEmptyRoomState() (map[string]string, error) { - resp, err := s.GetWithIdentifier(constants.ClassroomQueryURL) +// 抽象成一个函数, 因为基本上每个请求都需要这两个参数 +func (s *Student) getState(url string) (map[string]string, error) { + resp, err := s.GetWithIdentifier(url) if err != nil { return nil, err } @@ -251,3 +254,60 @@ func parseEmptyRoom(doc *html.Node) ([]string, error) { } return res, nil } + +// 考场查询 +func (s *Student) GetExamRoom(req ExamRoomReq) ([]*ExamRoomInfo, error) { + viewStateMap, err := s.getState(constants.ExamRoomQueryURL) + if err != nil { + return nil, err + } + res, err := s.PostWithIdentifier(constants.ExamRoomQueryURL, map[string]string{ + "__VIEWSTATE": viewStateMap["VIEWSTATE"], + "__EVENTVALIDATION": viewStateMap["EVENTVALIDATION"], + "ctl00$ContentPlaceHolder1$DDL_xnxq": req.Term, + "ctl00$ContentPlaceHolder1$BT_submit": "确定", + }) + if err != nil { + return nil, err + } + examInfos, err := parseExamRoom(res) + if err != nil { + return nil, err + } + return examInfos, nil +} + +func parseExamRoom(doc *html.Node) ([]*ExamRoomInfo, error) { + var examInfos []*ExamRoomInfo + sel := htmlquery.FindOne(doc, "//*[@id=\"ContentPlaceHolder1_DataList_xxk\"]") + rows := htmlquery.Find(sel, ".//tr[@onmouseover]") + for _, row := range rows { + // 提取单元格内容 + cells := htmlquery.Find(row, "./td") + // 获取每一列的内容 + courseName := strings.TrimSpace(htmlquery.InnerText(cells[0])) + credit := strings.TrimSpace(htmlquery.InnerText(cells[1])) + teacher := strings.TrimSpace(htmlquery.InnerText(cells[2])) + dateTimeAndLocation := strings.TrimSpace(htmlquery.InnerText(cells[3])) + // 如果为空,说明目前没有安排考试 + if dateTimeAndLocation == "" { + continue + } + // example: 2024年11月17日 12:30-17:30 旗山数计3-404 + array := strings.Fields(dateTimeAndLocation) + date := array[0] + time := array[1] + location := array[2] + // 将数据存入结构体 + examInfo := &ExamRoomInfo{ + CourseName: courseName, + Credit: credit, + Teacher: teacher, + Date: date, + Time: time, + Location: location, + } + examInfos = append(examInfos, examInfo) + } + return examInfos, nil +}