2026-05-11 00:46:38 +08:00
|
|
|
|
package parser
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"strings"
|
|
|
|
|
|
|
2026-06-16 18:33:13 +08:00
|
|
|
|
"schedule_converter/models"
|
2026-05-11 00:46:38 +08:00
|
|
|
|
|
|
|
|
|
|
"github.com/PuerkitoBio/goquery"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2026-06-16 18:33:13 +08:00
|
|
|
|
// examTypeToCode 将考试类型映射为教务系统的请求码。
|
|
|
|
|
|
func examTypeToCode(t models.ExamType) string {
|
2026-05-11 00:46:38 +08:00
|
|
|
|
switch t {
|
2026-06-16 18:33:13 +08:00
|
|
|
|
case models.ExamTypeMidterm:
|
2026-05-11 00:46:38 +08:00
|
|
|
|
return "02"
|
2026-06-16 18:33:13 +08:00
|
|
|
|
case models.ExamTypeMakeup:
|
2026-05-11 00:46:38 +08:00
|
|
|
|
return "03"
|
|
|
|
|
|
default:
|
|
|
|
|
|
return "01"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-16 18:33:13 +08:00
|
|
|
|
// ExamTypeCode 返回考试类型对应的请求码(供 client 层构造请求使用)。
|
|
|
|
|
|
func ExamTypeCode(t models.ExamType) string {
|
|
|
|
|
|
return examTypeToCode(t)
|
2026-05-11 00:46:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-16 18:33:13 +08:00
|
|
|
|
// ParseExamHTML 解析考试安排页面 HTML,返回考试条目列表。
|
|
|
|
|
|
func ParseExamHTML(html string, examType models.ExamType) ([]models.ExamEntry, error) {
|
2026-05-11 00:46:38 +08:00
|
|
|
|
doc, err := goquery.NewDocumentFromReader(strings.NewReader(html))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-16 18:33:13 +08:00
|
|
|
|
var exams []models.ExamEntry
|
2026-05-11 00:46:38 +08:00
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
2026-06-16 18:33:13 +08:00
|
|
|
|
exam := models.ExamEntry{
|
2026-05-11 00:46:38 +08:00
|
|
|
|
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
|
2026-06-16 18:33:13 +08:00
|
|
|
|
}
|