Files
schedule_converter/parser/exam.go

128 lines
2.6 KiB
Go
Raw Normal View History

package parser
import (
"fmt"
"net/http"
"strings"
"schedule_converter/client"
"schedule_converter/config"
"github.com/PuerkitoBio/goquery"
)
type ExamType string
const (
ExamTypeFinal ExamType = "final"
ExamTypeMidterm ExamType = "midterm"
ExamTypeMakeup ExamType = "makeup"
)
type ExamEntry struct {
Course string
Date string
Time string
Week string
Weekday string
Type ExamType
}
func examTypeToCode(t ExamType) string {
switch t {
case ExamTypeMidterm:
return "02"
case ExamTypeMakeup:
return "03"
default:
return "01"
}
}
func FetchExams(httpClient *http.Client, examType ExamType) ([]ExamEntry, error) {
examURL := config.BaseURL + "/kscx/queryKsForXs"
fmt.Printf("[考试] 正在获取考试时间数据 (%s)...\n", examType)
data := fmt.Sprintf("xnxq=&kssjd=%s", examTypeToCode(examType))
req, err := http.NewRequest("POST", examURL, strings.NewReader(data))
if err != nil {
return nil, err
}
req.Header = client.GetHeadersWithContentType("application/x-www-form-urlencoded")
resp, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
html, err := decodeResponseBody(resp)
if err != nil {
return nil, err
}
exams, err := ParseExamTimeHTML(html, examType)
if err != nil {
return nil, err
}
fmt.Printf("[考试] 共获取 %d 条考试记录 (%s)\n", len(exams), examType)
return exams, nil
}
func FetchAllExams(httpClient *http.Client) ([]ExamEntry, error) {
var allExams []ExamEntry
for _, et := range []ExamType{ExamTypeFinal, ExamTypeMidterm, ExamTypeMakeup} {
exams, err := FetchExams(httpClient, et)
if err != nil {
fmt.Printf("[考试] 获取%s考试失败: %v\n", et, err)
continue
}
allExams = append(allExams, exams...)
}
return allExams, nil
}
func ParseExamTimeHTML(html string, examType ExamType) ([]ExamEntry, error) {
doc, err := goquery.NewDocumentFromReader(strings.NewReader(html))
if err != nil {
return nil, err
}
var exams []ExamEntry
doc.Find("table.bot_line").Each(func(_ int, table *goquery.Selection) {
rows := table.Find("tr")
if rows.Length() < 2 {
return
}
rows.Each(func(idx int, row *goquery.Selection) {
if idx == 0 {
return
}
cells := row.Find("td")
if cells.Length() < 6 {
return
}
texts := getCellTexts(cells)
exam := ExamEntry{
Course: safeGet(texts, 1),
Date: safeGet(texts, 2),
Time: safeGet(texts, 3),
Week: safeGet(texts, 4),
Weekday: safeGet(texts, 5),
Type: examType,
}
if exam.Course != "" && len(exam.Course) >= 2 {
exams = append(exams, exam)
}
})
})
return exams, nil
}