Skip to content

Commit f1d5fac

Browse files
committed
update: v2.0.0
1 parent 9687af2 commit f1d5fac

File tree

5 files changed

+57
-43
lines changed

5 files changed

+57
-43
lines changed

README.md

+11-20
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@ Twinte内部で利用するために開発された
99
## KdBDownloader
1010
KDBからCSVファイルをダウンロードする。
1111

12-
js例
13-
```js
14-
const csv = await require('twinte-parser').downloadKDB()
15-
```
16-
ts例
1712
```typescript
1813
import { donwloadKDB } from 'twinte-parser'
1914

@@ -23,18 +18,12 @@ const csv = await downloadKDB()
2318
## Parser
2419
KdBから取得したcsvをオブジェクトに変換する。
2520

26-
js例
27-
```js
28-
const classes = require('twinte-parser').parseKDB(csv)
29-
```
30-
31-
ts例
3221
```typescript
3322
import parseKDB from 'twinte-parser'
3423
// or
3524
import { parseKDB } from 'twinte-parser'
3625

37-
const classes = parseKDB(csv)
26+
const courses = parseKDB(csv)
3827
```
3928

4029
##
@@ -70,35 +59,37 @@ enum Day {
7059

7160
```
7261

73-
### Lecture
62+
### Course
7463
```typescript
75-
interface Lecture {
76-
lectureCode: string
64+
interface Course {
65+
code: string
7766
name: string
7867
credits: number
7968
overview: string
8069
remarks: string
8170
type: number
82-
year: number[]
83-
details: {
71+
recommendedGrade: number[]
72+
schedules: {
8473
module: Module
8574
day: Day
8675
period: number
8776
room: string
8877
}[]
8978
instructor: string
79+
lastUpdate: Date
80+
error: boolean
9081
}
9182
```
9283

93-
ここで`details`が配列になっていることに注意。
84+
ここで`schedules`が配列になっていることに注意。
9485

9586
例えば春AB・月曜1限・3A201の授業があった場合、
9687

9788
```typescript
9889
{
99-
id: 'XXXXXXX',
90+
code: 'XXXXXXX',
10091
name: "名前",
101-
details: [
92+
schedules: [
10293
{
10394
module: "春A",
10495
day: "",

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "twinte-parser",
3-
"version": "1.3.2",
3+
"version": "2.0.0",
44
"description": "Twinte内部で使用するために開発されたKdBパーサ",
55
"private": false,
66
"main": "dist/index.js",

src/app.ts

+10-9
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import * as fs from 'fs'
2-
import kdbGetter from './kdbDownloader'
2+
import downloadKdb from './kdbDownloader'
33
import parse from './parser'
44
import * as colors from 'colors'
55
import * as commandLineArgs from 'command-line-args'
66

7-
console.log('twinte-parser v1.3.2')
7+
console.log('twinte-parser v2.0.0')
88

99
const ops = commandLineArgs([
1010
{ name: 'year', alias: 'y', defaultValue: undefined },
@@ -14,17 +14,18 @@ const main = async () => {
1414
let xlsx: Buffer
1515

1616
if (fs.existsSync('./kdb.xlsx')) {
17-
console.log('i Cache file (kdb.xlsx) found.')
17+
console.log('Cache file (kdb.xlsx) found.')
1818
xlsx = fs.readFileSync('./kdb.xlsx')
1919
} else {
20-
xlsx = await kdbGetter(ops.year)
20+
console.log('Downloading xlsx from kdb.\nIt may take a few minutes.')
21+
xlsx = await downloadKdb(ops.year)
2122
fs.writeFileSync('./kdb.xlsx', xlsx)
2223
}
23-
const classes = parse(xlsx)
24-
fs.writeFileSync('data.json', JSON.stringify(classes))
25-
console.log(
26-
'Parsed data has been saved at ${working directory}/data.json'
27-
)
24+
console.log('parsing...')
25+
const courses = parse(xlsx)
26+
console.log(`${courses.length} courses have been parsed.`)
27+
fs.writeFileSync('data.json', JSON.stringify(courses))
28+
console.log('Data has been saved at ./data.json')
2829
}
2930

3031
main()

src/kdbDownloader.ts

+33-7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,20 @@ import _axiosCookiejarSupport from 'axios-cookiejar-support'
33
import * as iconv from 'iconv-lite'
44
import * as fs from 'fs'
55
import * as colors from 'colors'
6+
import * as assert from 'assert'
7+
8+
export class NoCoursesFoundError extends Error {
9+
public constructor() {
10+
super('Search results are empty')
11+
Object.defineProperty(this, 'name', {
12+
configurable: true,
13+
enumerable: false,
14+
value: this.constructor.name,
15+
writable: true,
16+
})
17+
Error.captureStackTrace(this, NoCoursesFoundError)
18+
}
19+
}
620

721
_axiosCookiejarSupport(_axios)
822

@@ -26,15 +40,18 @@ const grantSession = async (): Promise<string> => {
2640
return extractFlowExecutionKey(iconv.decode(res.data, 'utf8'))
2741
}
2842

29-
const searchAll = async (flowExecutionKey: string): Promise<string> => {
43+
const searchAll = async (
44+
flowExecutionKey: string,
45+
year: number
46+
): Promise<string> => {
3047
const res = await axios.post<Buffer>(
3148
'https://kdb.tsukuba.ac.jp/campusweb/campussquare.do',
3249
postBody({
3350
_flowExecutionKey: flowExecutionKey,
3451
_eventId: 'searchOpeningCourse',
3552
index: '',
3653
locale: '',
37-
nendo: 2020,
54+
nendo: year,
3855
termCode: '',
3956
dayCode: '',
4057
periodCode: '',
@@ -51,18 +68,23 @@ const searchAll = async (flowExecutionKey: string): Promise<string> => {
5168
outputFormat: 0,
5269
})
5370
)
54-
return extractFlowExecutionKey(iconv.decode(res.data, 'utf8'))
71+
const html = iconv.decode(res.data, 'utf8')
72+
if (html.includes('(全部で 0件あります)')) throw new NoCoursesFoundError()
73+
return extractFlowExecutionKey(html)
5574
}
5675

57-
const downloadExcel = async (flowExecutionKey: string): Promise<Buffer> => {
76+
const downloadExcel = async (
77+
flowExecutionKey: string,
78+
year
79+
): Promise<Buffer> => {
5880
const res = await axios.post<Buffer>(
5981
'https://kdb.tsukuba.ac.jp/campusweb/campussquare.do',
6082
postBody({
6183
_flowExecutionKey: flowExecutionKey,
6284
_eventId: 'outputOpeningCourseExcel',
6385
index: '',
6486
locale: '',
65-
nendo: 2020,
87+
nendo: year,
6688
termCode: '',
6789
dayCode: '',
6890
periodCode: '',
@@ -79,6 +101,10 @@ const downloadExcel = async (flowExecutionKey: string): Promise<Buffer> => {
79101
outputFormat: 1,
80102
})
81103
)
104+
assert(
105+
res.headers.contentType !==
106+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet .xlsx; charset=UTF-8'
107+
)
82108
return res.data
83109
}
84110

@@ -90,6 +116,6 @@ export default async (
90116
): Promise<Buffer> => {
91117
let flowExecutionKey = ''
92118
flowExecutionKey = await grantSession()
93-
flowExecutionKey = await searchAll(flowExecutionKey)
94-
return downloadExcel(flowExecutionKey)
119+
flowExecutionKey = await searchAll(flowExecutionKey, year)
120+
return downloadExcel(flowExecutionKey, year)
95121
}

src/parser.ts

+2-6
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ const analyzeRow = (columns: string[]) => {
128128
const periodString = columns[6]
129129
const roomString = columns[7]
130130

131-
// 空文字は省く
132131
const moduleArray = moduleString.split('\r\n')
133132
const periodArray = periodString.split('\r\n')
134133
const roomArray = roomString.split('\r\n')
@@ -145,7 +144,6 @@ const analyzeRow = (columns: string[]) => {
145144
(roomArray.length === count || roomArray.length === 1)
146145
)
147146
) {
148-
console.log('Warning!')
149147
courseData.error = true
150148
}
151149

@@ -171,22 +169,20 @@ const analyzeRow = (columns: string[]) => {
171169
}
172170

173171
/**
174-
* CSVをパースする
175-
* @param csv KDBからダウンロードしたcsv文字列
172+
* Excelファイルをパースする
173+
* @param data xlsxファイルのバイナリ
176174
*/
177175
export default (data: Buffer): Course[] => {
178176
const sheet = readXLSX(data).Sheets['開設科目一覧']
179177

180178
const courses: Course[] = []
181179

182-
console.log('● Parsing')
183180
for (let r = 5; ; r++) {
184181
const columns: string[] = []
185182
for (let c = 0; c <= 16; c++)
186183
columns.push(sheet[utils.encode_cell({ r, c })].v)
187184
if (columns[0] === '') break
188185
courses.push(analyzeRow(columns))
189186
}
190-
console.log('✔ Done')
191187
return courses
192188
}

0 commit comments

Comments
 (0)