docs: how to parse Comcigan
This commit is contained in:
parent
3366610c5d
commit
348189ef62
2 changed files with 109 additions and 8 deletions
18
README.md
18
README.md
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
[컴시간알리미](http://컴시간학생.kr)를 파싱하는 TypeScript 라이브러리입니다.
|
||||
|
||||
컴시간알리미의 구조 및 파싱 방법은 [docs/README.md](./docs/README.md)를 참고해주세요.
|
||||
|
||||
## 설치
|
||||
|
||||
```bash
|
||||
|
|
@ -16,17 +18,17 @@ pnpm add comcigan.ts # pnpm
|
|||
## 사용 예시
|
||||
|
||||
```typescript
|
||||
import Comcigan, { School, Weekday } from 'comcigan.ts'
|
||||
import Comcigan, { School, Weekday } from "comcigan.ts";
|
||||
|
||||
const comcigan = new Comcigan()
|
||||
const comcigan = new Comcigan();
|
||||
|
||||
const main = async () => {
|
||||
const searchedSchools = await comcigan.searchSchools('학교 이름') // 학교 검색
|
||||
const school = await School.fromName('학교 이름') // 바로 불러오기 (== searchedSchools[0])
|
||||
const searchedSchools = await comcigan.searchSchools("학교 이름"); // 학교 검색
|
||||
const school = await School.fromName("학교 이름"); // 바로 불러오기 (== searchedSchools[0])
|
||||
|
||||
console.log(await school.getTimetable(3, 3, Weekday.Friday)) // 3학년 3반 금요일 시간표
|
||||
console.log(await comcigan.getTimetable(school.code, 3, 3, Weekday.Friday)) // 학교 코드를 이용하는 방법
|
||||
}
|
||||
console.log(await school.getTimetable(3, 3, Weekday.Friday)); // 3학년 3반 금요일 시간표
|
||||
console.log(await comcigan.getTimetable(school.code, 3, 3, Weekday.Friday)); // 학교 코드를 이용하는 방법
|
||||
};
|
||||
|
||||
main()
|
||||
main();
|
||||
```
|
||||
|
|
|
|||
99
docs/README.md
Normal file
99
docs/README.md
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
# How to parse Comcigan - 2024/07/14
|
||||
|
||||
> [!WARNING]
|
||||
> 컴시간알리미 측에선 3rd party 앱을 허용하지 않기 때문에, 이 문서에서 설명할 방법은 언제든지 작동을 멈출 수 있습니다. 또한 이 문서는 오로지 학습 목적으로 작성되었으며, 이를 통해 발생하는 모든 문제에 대해 작성자는 책임지지 않습니다.
|
||||
|
||||
이 문서에선 컴시간알리미를 파싱하는 방법에 대해서 설명합니다.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Base URL: `http://comci.net:4082` (protocol이 `http`인 것에 주의)
|
||||
|
||||
User-Agent에 따라 요청을 거부하는 경우가 있으므로, User-Agent를 브라우저의 것과 동일하게 설정하는 것을 추천합니다.
|
||||
|
||||
컴시간알리미는 일정 주기마다 (24시간으로 추정) 모든 route와 응답의 구조를 변형합니다. 따라서 `GET /st`을 요청해 응답을 `EUC-KR`로 디코딩한 뒤, 아래 테이블의 정규표현식을 사용해 route와 code를 추출해야 합니다.
|
||||
|
||||
| Name | RegExp |
|
||||
| -------------- | ----------------------------------- |
|
||||
| mainRoute | `(?<=\.\/)\d+(?=\?\d+l)` |
|
||||
| searchRoute | `(?<=\?)\d+(?=l)` |
|
||||
| timetableRoute | `(?<=')\d+(?=_')` |
|
||||
| teacherCode | `(?<=성명=자료\.자료)\d+` |
|
||||
| originalCode | `(?<=원자료=Q자료\(자료.자료)\d+` |
|
||||
| dayCode | `(?<=일일자료=Q자료\(자료.자료)\d+` |
|
||||
| subjectCode | `(?<=자료.자료)\d+(?=\[sb\])` |
|
||||
|
||||
또한 `GET /st`를 제외한 모든 응답은 `Null` 문자들을 포함하고 있기 때문에 이를 제거해야 파싱이 수월합니다. 후술할 내용들은 모두 응답의 `Null` 문자들을 제거한다는 가정하에 작성되었습니다.
|
||||
|
||||
## Endpoints
|
||||
|
||||
### 학교 검색
|
||||
|
||||
학교를 검색하기 위해선 먼저 학교 이름을 EUC-KR로 encode해야 합니다. 이후 `GET /{mainRoute}?{searchRoute}l{인코딩된 학교 이름}`을 요청하면 다음과 같은 응답을 받을 수 있습니다.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"학교검색": [
|
||||
{
|
||||
12345, // 지역 코드 (확실하지 않음)
|
||||
"서울", // 지역 이름
|
||||
"ㅇㅇ중학교", // 학교 이름
|
||||
12345 // 학교 코드
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 시간표 조회
|
||||
|
||||
시간표를 조회하기 위해선 상술한 학교 검색을 통해 학교 코드를 알아내야 합니다. 이후 `{timetableRoute}_{학교 코드}_0_1`을 `base64`로 encode하고, `GET /{mainRoute}?{인코딩된 param}`를 요청하면 다음과 같은 응답을 받을 수 있습니다.
|
||||
|
||||
> [!NOTE]
|
||||
> '원자료'는 원래 일과 시간표, '일자료'는 일일 시간표를 의미합니다. 원자료와 일자료는 다를 수 있고, 특정 교시에 대해선 둘 중 하나만 존재할 수도 있습니다.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"자료{teacherCode}": [
|
||||
"*", // 교사의 개인정보 보호를 위해 사용되는 문자
|
||||
"ㄱㄴ*",
|
||||
"ㄹㅁ*",
|
||||
...
|
||||
],
|
||||
"자료{subjectCode}": [
|
||||
12, // 과목 개수
|
||||
"국어",
|
||||
...
|
||||
],
|
||||
"자료{originalCode}": [
|
||||
3, // 원자료 학년 개수
|
||||
[
|
||||
10, // 원자료 1학년 반 개수
|
||||
[
|
||||
5, // 원자료 1학년 1반 요일 개수
|
||||
[
|
||||
6, // 원자료 1학년 1반 월요일 교시 개수
|
||||
12345, // 원자료 1학년 1반 월요일 1교시 코드
|
||||
...
|
||||
],
|
||||
...
|
||||
],
|
||||
...
|
||||
],
|
||||
...
|
||||
],
|
||||
"자료{dayCode}": [
|
||||
/* 원자료와 구조 동일 */
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
교시 코드에서 교사와 과목을 알아내기 위해선 다음과 같은 작업이 필요합니다.
|
||||
|
||||
1. `teachersLen`을 다음과 같이 정의합니다. (교사 수를 10진수로 표현했을 때의 자릿수를 의미합니다)
|
||||
|
||||
$$\lfloor \log_{10}(\text{{amount of teachers}}) \rfloor + 1$$
|
||||
|
||||
2. 교시 코드에서 마지막 `teachersLen + 1`자리를 제외하면 교사 코드를 얻을 수 있고, 응답의 `자료{teacherCode}`에서 index `교사 코드`의 값이 교사 이름입니다.
|
||||
|
||||
3. 교시 코드의 마지막 `teachersLen`자리는 과목 코드이고, 응답의 `자료{subjectCode}`에서 index `과목 코드`의 값이 과목 이름입니다.
|
||||
Loading…
Add table
Add a link
Reference in a new issue