Documentation
¶
Overview ¶
Package ntpu provides scrapers for NTPU websites including student ID, course catalog, and contact directory information.
Index ¶
- Constants
- Variables
- func BuildContactSearchURL(searchTerm string) string
- func ExtractYear(studentID string) int
- func GetDegreeTypeName(studentID string) string
- func IsLawDepartment(deptCode string) bool
- func ProbeCoursesExist(ctx context.Context, client *scraper.Client, year, term int) (bool, error)
- func ScrapeAcademicContacts(ctx context.Context, client *scraper.Client) ([]*storage.Contact, error)
- func ScrapeAdministrativeContacts(ctx context.Context, client *scraper.Client) ([]*storage.Contact, error)
- func ScrapeContacts(ctx context.Context, client *scraper.Client, searchTerm string) ([]*storage.Contact, error)
- func ScrapeCourseByUID(ctx context.Context, client *scraper.Client, uid string) (*storage.Course, error)
- func ScrapeCourses(ctx context.Context, client *scraper.Client, year, term int, title string) ([]*storage.Course, error)
- func ScrapeCoursesByTeacher(ctx context.Context, client *scraper.Client, year, term int, ...) ([]*storage.Course, error)
- func ScrapeCoursesByYear(ctx context.Context, client *scraper.Client, year int) ([]*storage.Course, error)
- func ScrapeStudentByID(ctx context.Context, client *scraper.Client, studentID string) (*storage.Student, error)
- func ScrapeStudentsByYear(ctx context.Context, client *scraper.Client, year int, ...) ([]*storage.Student, error)
- type ProgramFolder
- type ProgramInfo
Constants ¶
const ( StudentTypeContinuing = "3" // 進修學士班 StudentTypeUndergrad = "4" // 大學部/學士班 StudentTypeMaster = "7" // 碩士班 StudentTypePhD = "8" // 博士班 )
Student type prefixes for scraping
const ( DegreeNameContinuing = "進修學士班" DegreeNameBachelor = "學士班" DegreeNameMaster = "碩士班" DegreeNamePhD = "博士班" DegreeNameUnknown = "國立臺北大學" // Fallback for invalid/unknown prefix )
DegreeTypeName constants for user-facing display (標準名稱)
Variables ¶
var DepartmentCodes = map[string]string{
"法律": "71",
"法學": "712",
"司法": "714",
"財法": "716",
"公行": "72",
"經濟": "73",
"社學": "742",
"社工": "744",
"財政": "75",
"不動": "76",
"會計": "77",
"統計": "78",
"企管": "79",
"金融": "80",
"中文": "81",
"應外": "82",
"歷史": "83",
"休運": "84",
"資工": "85",
"通訊": "86",
"電機": "87",
}
DepartmentCodes maps department names to codes (大學部). Note: "法律" and base codes for 社學/社工 require 3rd digit from student ID
var DepartmentNames = reverseMap(DepartmentCodes)
DepartmentNames provides reverse mappings: code -> name
var FullDepartmentCodes = map[string]string{
"法律學系": "71",
"法律學系法學組": "712",
"法律學系司法組": "714",
"法律學系財經法組": "716",
"公共行政暨政策學系": "72",
"經濟學系": "73",
"社會學系": "742",
"社會工作學系": "744",
"財政學系": "75",
"不動產與城鄉環境學系": "76",
"會計學系": "77",
"統計學系": "78",
"企業管理學系": "79",
"金融與合作經營學系": "80",
"中國文學系": "81",
"應用外語學系": "82",
"歷史學系": "83",
"休閒運動管理學系": "84",
"資訊工程學系": "85",
"通訊工程學系": "86",
"電機工程學系": "87",
}
FullDepartmentCodes maps full department names to codes (大學部)
var MasterDepartmentCodes = map[string]string{
"企業管理學系碩士班": "31",
"會計學系碩士班": "32",
"統計學系碩士班": "33",
"金融與合作經營學系碩士班": "34",
"國際企業研究所碩士班": "35",
"資訊管理研究所": "36",
"財務金融英語碩士學位學程": "37",
"民俗藝術與文化資產研究所": "41",
"古典文獻學研究所": "42",
"中國文學系碩士班": "43",
"歷史學系碩士班": "44",
"法律學系碩士班一般生組": "51",
"法律學系碩士班法律專業組": "52",
"經濟學系碩士班": "61",
"社會學系碩士班": "62",
"社會工作學系碩士班": "63",
"犯罪學研究所": "64",
"公共行政暨政策學系碩士班": "71",
"財政學系碩士班": "72",
"不動產與城鄉環境學系碩士班": "73",
"都市計劃研究所碩士班": "74",
"自然資源與環境管理研究所碩士班": "75",
"城市治理英語碩士學位學程": "76",
"會計學系碩士在職專班": "77",
"統計學系碩士在職專班": "78",
"企業管理學系碩士在職專班": "79",
"通訊工程學系碩士班": "81",
"電機工程學系碩士班": "82",
"資訊工程學系碩士班": "83",
"智慧醫療管理英語碩士學位學程": "91",
}
MasterDepartmentCodes maps master's program department names to codes (碩士班)
var MasterDepartmentNames = reverseMap(MasterDepartmentCodes)
MasterDepartmentNames provides reverse mappings for master degree programs: code -> name.
var MasterDeptCodes = []string{
"31",
"32",
"33",
"34",
"35",
"36",
"37",
"41",
"42",
"43",
"44",
"51",
"52",
"61",
"62",
"63",
"64",
"71",
"72",
"73",
"74",
"75",
"76",
"77",
"78",
"79",
"81",
"82",
"83",
"91",
}
MasterDeptCodes contains master's program department codes for scraping.
var PhDDepartmentCodes = map[string]string{
"企業管理學系博士班": "31",
"會計學系博士班": "32",
"法律學系博士班": "51",
"經濟學系博士班": "61",
"公共行政暨政策學系博士班": "71",
"不動產與城鄉環境學系博士班": "73",
"都市計劃研究所博士班": "74",
"自然資源與環境管理研究所博士班": "75",
"電機資訊學院博士班": "76",
}
PhDDepartmentCodes maps PhD program department names to codes (博士班)
var PhDDepartmentNames = reverseMap(PhDDepartmentCodes)
PhDDepartmentNames provides reverse mappings for PhD programs: code -> name.
var PhDDeptCodes = []string{
"31",
"32",
"51",
"61",
"71",
"73",
"74",
"75",
"76",
}
PhDDeptCodes contains PhD program department codes for scraping.
var UndergradDeptCodes = []string{
"71", "712", "714", "716",
"72",
"73",
"742", "744",
"75",
"76",
"77",
"78",
"79",
"80",
"81",
"82",
"83",
"84",
"85",
"86",
"87",
}
UndergradDeptCodes contains undergraduate department codes for scraping.
Functions ¶
func BuildContactSearchURL ¶ added in v1.2.6
BuildContactSearchURL generates the URL for viewing contact search results. The search term is encoded in Big5 format as required by the NTPU directory. Returns empty string if encoding fails. This is used for the "資料來源" button to open the original contact page.
func ExtractYear ¶ added in v1.3.5
ExtractYear extracts the academic year from a student ID. Example: 410571074 -> 105, 41121074 -> 112, 414185001 -> 114
func GetDegreeTypeName ¶ added in v1.3.6
GetDegreeTypeName returns the degree type display name based on student ID prefix. Returns the standard Chinese name: 進修學士班, 學士班, 碩士班, 博士班. Falls back to "國立臺北大學" if the prefix is invalid or empty.
func IsLawDepartment ¶
IsLawDepartment returns true if the department code belongs to Law School (71x). Used to determine if "組" should be used instead of "系" in display text.
func ProbeCoursesExist ¶ added in v1.3.6
ProbeCoursesExist performs a lightweight check if courses exist for a semester. Uses a single education code (U = undergraduate) to minimize HTTP requests. Returns true if any courses are found, false otherwise. This is specifically designed for warmup probing and should not be used for data collection.
func ScrapeAcademicContacts ¶
func ScrapeAcademicContacts(ctx context.Context, client *scraper.Client) ([]*storage.Contact, error)
ScrapeAcademicContacts scrapes all academic contacts Supports automatic URL failover across multiple SEA endpoints
func ScrapeAdministrativeContacts ¶
func ScrapeAdministrativeContacts(ctx context.Context, client *scraper.Client) ([]*storage.Contact, error)
ScrapeAdministrativeContacts scrapes all administrative contacts Supports automatic URL failover across multiple SEA endpoints
func ScrapeContacts ¶
func ScrapeContacts(ctx context.Context, client *scraper.Client, searchTerm string) ([]*storage.Contact, error)
ScrapeContacts scrapes contacts by search term URL: {baseURL}/pls/ld/CAMPUS_DIR_M.pq?q={searchTerm} The search term must be URL-encoded in Big5 encoding Supports automatic URL failover across multiple SEA endpoints with cache invalidation
func ScrapeCourseByUID ¶
func ScrapeCourseByUID(ctx context.Context, client *scraper.Client, uid string) (*storage.Course, error)
ScrapeCourseByUID scrapes a specific course by its UID (year+term+no) Example UID: 11312U123 (year=113, term=1, no=2U123) Supports automatic URL failover across multiple SEA endpoints
func ScrapeCourses ¶
func ScrapeCourses(ctx context.Context, client *scraper.Client, year, term int, title string) ([]*storage.Course, error)
ScrapeCourses scrapes courses by year, term, and optional filters For title search: uses POST to {baseURL}/pls/dev_stud/course_query_all.queryByAllConditions with 'cour' parameter For general query: uses GET to {baseURL}/pls/dev_stud/course_query_all.queryByKeyword with 'courseno' parameter When term=0, queries both semesters at once (more efficient for historical searches) Supports automatic URL failover across multiple SEA endpoints
func ScrapeCoursesByTeacher ¶ added in v1.1.2
func ScrapeCoursesByTeacher(ctx context.Context, client *scraper.Client, year, term int, teacherName string) ([]*storage.Course, error)
ScrapeCoursesByTeacher scrapes courses by teacher name Uses POST to {baseURL}/pls/dev_stud/course_query_all.queryByAllConditions with 'teach' parameter
func ScrapeCoursesByYear ¶
func ScrapeCoursesByYear(ctx context.Context, client *scraper.Client, year int) ([]*storage.Course, error)
ScrapeCoursesByYear scrapes ALL courses for a given year (both semesters) This is a convenience wrapper around ScrapeCourses with term=0 and empty title Note: Current warmup uses per-semester scraping (ScrapeCourses) for precise control
func ScrapeStudentByID ¶
func ScrapeStudentByID(ctx context.Context, client *scraper.Client, studentID string) (*storage.Student, error)
ScrapeStudentByID scrapes a specific student by their student ID URL: {baseURL}/portfolio/search.php?fmScope=2&page=1&fmKeyword={studentID} Supports automatic URL failover across multiple LMS endpoints
func ScrapeStudentsByYear ¶
func ScrapeStudentsByYear(ctx context.Context, client *scraper.Client, year int, deptCode, studentType string) ([]*storage.Student, error)
ScrapeStudentsByYear scrapes students by year, department code and student type. URL: {baseURL}/portfolio/search.php?fmScope=2&page=1&fmKeyword={studentType}{year}{deptCode} studentType: "4" for undergrad, "7" for master's, "8" for PhD Returns a list of students matching the criteria. Supports automatic URL failover across multiple LMS endpoints.
Types ¶
type ProgramFolder ¶ added in v1.2.0
ProgramFolder represents a category of programs on the LMS.
type ProgramInfo ¶ added in v1.2.0
ProgramInfo contains information about an academic program.
func ScrapePrograms ¶ added in v1.2.0
ScrapePrograms dynamically discovers all programs by crawling the LMS folders. It handles pagination automatically by detecting "Next" links. Supports automatic URL failover via URLCache.