Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 17e6e1421e | |||
| f8d2147fc9 | |||
| 6b80254e0b | |||
| 70d41cc4bc | |||
| 1cf4193ecb | |||
| 4485c14503 | |||
| f351e73844 | |||
| b6d20406f8 | |||
|
|
8ed796a2a5 | ||
| 4ea60b6a9e | |||
| bea92a83f0 | |||
| 856a44ad61 | |||
| ed7bad423c | |||
| d289a7af55 | |||
| b9c2089514 | |||
| acbc3296f2 | |||
| e4ebb36d4e | |||
| c24681aa1c | |||
| 2afa08efce | |||
| c61489ed9c | |||
|
|
db020f765f | ||
|
|
bf880ae585 | ||
|
|
6ea1bbf9c0 | ||
|
|
a3471b4f1d |
@ -41,6 +41,9 @@
|
||||
- [x] 把版排好(選課框框改成可下拉(才可以同時看到課表))
|
||||
|
||||
# 課程爬蟲使用說明
|
||||
> 因為學校教務系統更新通識分類的部份很慢,因此目前的程式碼已經修改成無法對應「通識課程分類」的版本,
|
||||
> 實際上線的 data 是依靠「工人智慧」,
|
||||
> 如果有需要爬取資料,建議使用較舊版本的 python code
|
||||
|
||||
安裝所需套件
|
||||
```
|
||||
|
||||
20
api.py
20
api.py
@ -5,19 +5,23 @@ import sqlite3
|
||||
from flask_cors import CORS
|
||||
|
||||
app = Flask(__name__)
|
||||
CORS(app, resources={r"/.*": {"origins": ["https://snsd0805.com"]}})
|
||||
CORS(app, resources={r"/.*": {"origins": ["https://course.snsd0805.com"]}})
|
||||
|
||||
def facebookAuth(token):
|
||||
url = "https://graph.facebook.com/v9.0/me?access_token={}"
|
||||
|
||||
response = requests.get(url.format(token))
|
||||
data = json.loads(response.text)
|
||||
|
||||
# 若 access code 通過 facebook 驗證
|
||||
if response.status_code == 200:
|
||||
return True, data['id'], data['name']
|
||||
else:
|
||||
try:
|
||||
response = requests.get(url.format(token), timeout=5)
|
||||
except:
|
||||
return False, None, None
|
||||
else:
|
||||
data = json.loads(response.text)
|
||||
|
||||
# 若 access code 通過 facebook 驗證
|
||||
if response.status_code == 200:
|
||||
return True, data['id'], data['name']
|
||||
else:
|
||||
return False, None, None
|
||||
|
||||
@app.route('/courseTable', methods=["GET"])
|
||||
def get():
|
||||
|
||||
137
generalCourse.in
Normal file
137
generalCourse.in
Normal file
@ -0,0 +1,137 @@
|
||||
department 特色通識—在地實踐
|
||||
994017
|
||||
994057
|
||||
994065
|
||||
994068
|
||||
994071
|
||||
994075
|
||||
994076
|
||||
994077
|
||||
994078
|
||||
994080
|
||||
994086
|
||||
994089
|
||||
994112
|
||||
994113
|
||||
994114
|
||||
department 特色通識—綠概念
|
||||
993062
|
||||
994001
|
||||
994012
|
||||
994020
|
||||
994024
|
||||
994074
|
||||
994027
|
||||
department 特色通識—東南亞
|
||||
992106
|
||||
994030
|
||||
994096
|
||||
994098
|
||||
994099
|
||||
994102
|
||||
994103
|
||||
994105
|
||||
994108
|
||||
994109
|
||||
994110
|
||||
994111
|
||||
994010
|
||||
department 自然—生命與科學
|
||||
993001
|
||||
993002
|
||||
993022
|
||||
993054
|
||||
993086
|
||||
993093
|
||||
993106
|
||||
993126
|
||||
993131
|
||||
993132
|
||||
993133
|
||||
993137
|
||||
993145
|
||||
993008
|
||||
department 自然—工程與科技
|
||||
993023
|
||||
993052
|
||||
993055
|
||||
993060
|
||||
993064
|
||||
993075
|
||||
993116
|
||||
993156
|
||||
993157
|
||||
993013
|
||||
993066
|
||||
993111
|
||||
993120
|
||||
993143
|
||||
department 社會—社經與管理
|
||||
991094
|
||||
992033
|
||||
992035
|
||||
992110
|
||||
992120
|
||||
992129
|
||||
992141
|
||||
992143
|
||||
992177
|
||||
992191
|
||||
992193
|
||||
992203
|
||||
992205
|
||||
992213
|
||||
992214
|
||||
992216
|
||||
992217
|
||||
992223
|
||||
992062
|
||||
992211
|
||||
992232
|
||||
department 社會—法政與教育
|
||||
984003
|
||||
992076
|
||||
992108
|
||||
992112
|
||||
992178
|
||||
992179
|
||||
992180
|
||||
992188
|
||||
992206
|
||||
992234
|
||||
992185
|
||||
department 人文—歷史哲學與文化
|
||||
991068
|
||||
991075
|
||||
991087
|
||||
991140
|
||||
991144
|
||||
991154
|
||||
991163
|
||||
991192
|
||||
991199
|
||||
991212
|
||||
992073
|
||||
992087
|
||||
992171
|
||||
994044
|
||||
department 人文—文學與藝術
|
||||
460135
|
||||
991040
|
||||
991062
|
||||
991065
|
||||
991069
|
||||
991167
|
||||
991170
|
||||
991183
|
||||
991190
|
||||
991193
|
||||
991201
|
||||
991203
|
||||
991207
|
||||
991209
|
||||
991210
|
||||
991211
|
||||
992176
|
||||
991032
|
||||
991071
|
||||
182
getData.py
182
getData.py
@ -4,33 +4,39 @@ import os
|
||||
import csv
|
||||
from bs4 import BeautifulSoup as bs
|
||||
|
||||
USERNAME = ""
|
||||
PASSWORD = ""
|
||||
YEAR = 1111
|
||||
|
||||
header = {
|
||||
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:79.0) Gecko/20100101 Firefox/79.0',
|
||||
'Cookie': '輸入登入暨大教務系統後所得到的cookie'
|
||||
}
|
||||
session = requests.Session()
|
||||
|
||||
mainURL = "https://ccweb.ncnu.edu.tw/student/"
|
||||
courses = []
|
||||
generalCourse = []
|
||||
|
||||
def getGeneralCourseData(year):
|
||||
'''
|
||||
透過年份取得 通識課程分類的csv檔
|
||||
供後續課程對應。
|
||||
|
||||
先儲存到 generalCourse list,後續再用 courseID 對應通識分類
|
||||
'''
|
||||
def login(username, password):
|
||||
global session
|
||||
response = session.get('https://ccweb.ncnu.edu.tw/student/login.php')
|
||||
root = bs(response.text, 'html.parser')
|
||||
loginToken = root.find('input', {'name': 'token'}).get('value')
|
||||
|
||||
# 教務系統有開放 年度的query
|
||||
# 但實際操作後似乎僅開放當前學年度
|
||||
response = requests.get(mainURL+"aspmaker_student_common_rank_courses_viewlist.php?x_studentid=0&z_studentid=LIKE&x_year={}&z_year=%3D&cmd=search&export=csv".format(year), headers=header)
|
||||
data = response.text
|
||||
# request login page
|
||||
response = session.post(
|
||||
"https://ccweb.ncnu.edu.tw/student/login.php",
|
||||
data={
|
||||
'token': loginToken,
|
||||
'modal': '0',
|
||||
'username': username,
|
||||
'password': password,
|
||||
'type': 'a'
|
||||
}
|
||||
)
|
||||
|
||||
courses = data.split('\r\n')[1:-1]
|
||||
for course in courses:
|
||||
course = course.split(',')
|
||||
generalCourse.append(course)
|
||||
# 成功的話 return http 302, redirect
|
||||
if len(response.history)!=0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def curlDepartmentCourseTable(year):
|
||||
'''
|
||||
@ -39,74 +45,94 @@ def curlDepartmentCourseTable(year):
|
||||
'''
|
||||
print("取得所有課程資料:")
|
||||
|
||||
response = requests.get(mainURL+"aspmaker_course_opened_semester_stat_viewlist.php?x_year={}&recperpage=ALL".format(year), headers=header)
|
||||
data = response.text
|
||||
root = bs(data, "html.parser")
|
||||
|
||||
count = 1
|
||||
departmentsTR = root.findAll('tr')[1:] # 清除 thead
|
||||
for tr in departmentsTR:
|
||||
name = tr.findAll('td')[4].find('span').find('span').string # 取得 科系名稱
|
||||
link = mainURL + tr.find('a').get('data-url').replace('amp;', '') # 清除不必要符號, 取得 連結
|
||||
print("擷取{}課程... ({}/{})...".format(name, count, len(departmentsTR)))
|
||||
count += 1
|
||||
extractDepartmentCourseTable(name, link) # 透過連結 開始擷取 各科系課程
|
||||
# 切換年度,應該是用 cookie 儲存當前閱覽的年份
|
||||
url = 'https://ccweb6.ncnu.edu.tw/student/aspmaker_course_opened_detail_viewlist.php?cmd=search&t=aspmaker_course_opened_detail_view&z_year=%3D&x_year={}&z_courseid=%3D&x_courseid=&z_cname=LIKE&x_cname=&z_deptid=%3D&x_deptid=&z_division=LIKE&x_division=&z_grade=%3D&x_grade=&z_teachers=LIKE&x_teachers=&z_not_accessible=LIKE&x_not_accessible='
|
||||
response = session.get(url.format(year))
|
||||
|
||||
def extractDepartmentCourseTable(departmentName, link):
|
||||
# 取得 所有課程的 csv
|
||||
response = session.get('https://ccweb6.ncnu.edu.tw/student/aspmaker_course_opened_detail_viewlist.php?export=csv')
|
||||
with open("allCourses.csv", "wb") as fp:
|
||||
fp.write(response.content)
|
||||
|
||||
def extractDepartmentCourseTable(year):
|
||||
'''
|
||||
透過各科系連結取得課程資訊
|
||||
若為通識類別還要跟csv檔資料做對應,取得正確通識類別
|
||||
|
||||
對應後存取到 output.json
|
||||
'''
|
||||
response = requests.get(link, headers=header)
|
||||
data = response.text
|
||||
root = bs(data, "html.parser")
|
||||
with open("allCourses.csv") as fp:
|
||||
csvData = fp.read()
|
||||
|
||||
courseTR = root.findAll('tr')[1:] # 清除 thead
|
||||
for tr in courseTR:
|
||||
courseObj = {}
|
||||
tds = tr.find_all('td')
|
||||
|
||||
courseObj['link'] = mainURL + tds[0].find('a').get('href')
|
||||
courseObj['year'] = tds[1].find('span').string
|
||||
courseObj['number'] = tds[2].find('span').string
|
||||
courseObj['class'] = tds[3].find('span').string
|
||||
courseObj['name'] = tds[4].find('span').string
|
||||
courseObj['department'] = tds[5].find('span').string
|
||||
courseObj['graduated'] = tds[6].find('span').string
|
||||
courseObj['grade'] = tds[7].find('span').string
|
||||
courseObj['teacher'] = tds[8].find('span').string
|
||||
courseObj['place'] = tds[9].find('span').string
|
||||
courseObj['time'] = tds[11].find('span').string
|
||||
|
||||
if courseObj['department']=="99, 通識" :
|
||||
flag = False
|
||||
for row in generalCourse:
|
||||
if row[2] == '"{}"'.format(courseObj['number']):
|
||||
courseObj['department'] = row[0].replace('"', '')
|
||||
generalCourse.remove(row)
|
||||
flag = True
|
||||
break
|
||||
if not flag:
|
||||
print(" - 找不到對應的通識類別: {} ( {} )".format(courseObj['name'], courseObj['number']))
|
||||
ans = []
|
||||
courses = csvData.split('"\n')[1:-1]
|
||||
for course in courses:
|
||||
course = course.replace('\n', '.')
|
||||
# print(course)
|
||||
data = course[1:].split('","')
|
||||
|
||||
courses.append(courseObj)
|
||||
|
||||
with open('output.json', 'w') as fp:
|
||||
json.dump(courses, fp)
|
||||
courseObj = {}
|
||||
|
||||
baseLink = "https://ccweb6.ncnu.edu.tw/student/aspmaker_course_opened_detail_viewlist.php?cmd=search&t=aspmaker_course_opened_detail_view&z_year=%3D&x_year={}&x_courseid={}"
|
||||
courseObj['link'] = baseLink.format(year, data[1].zfill(6))
|
||||
courseObj['year'] = data[0]
|
||||
courseObj['number'] = data[1]
|
||||
courseObj['class'] = data[2]
|
||||
courseObj['name'] = data[3]
|
||||
courseObj['department'] = data[4]
|
||||
courseObj['graduated'] = data[6]
|
||||
courseObj['grade'] = data[7]
|
||||
courseObj['teacher'] = data[8]
|
||||
courseObj['place'] = data[9]
|
||||
courseObj['time'] = data[13].replace(' ', '')
|
||||
courseObj['credit'] = data[14]
|
||||
|
||||
ans.append(courseObj)
|
||||
|
||||
with open("歷年課程資料/{}_output.json".format(year), 'w') as fp:
|
||||
json.dump(ans, fp, ensure_ascii=False)
|
||||
|
||||
def updateGeneralCourse():
|
||||
with open("歷年課程資料/{}_output.json".format(YEAR)) as fp:
|
||||
courses = json.load(fp)
|
||||
|
||||
with open("generalCourse.in") as fp:
|
||||
line = fp.readline()
|
||||
while line:
|
||||
count = 0
|
||||
line = line.split()
|
||||
if len(line) == 2:
|
||||
department = line[1]
|
||||
else:
|
||||
for course in courses:
|
||||
if course['number'] == line[0]:
|
||||
course['department'] = department
|
||||
count += 1
|
||||
if count == 0 and len(line) != 2:
|
||||
print("{} 可能輸入錯誤 - {}".format(line[0], department))
|
||||
line = fp.readline()
|
||||
|
||||
print("還沒有對應到的課程:")
|
||||
for course in courses:
|
||||
if course['department'] == "99, 通識":
|
||||
course['department'] = "99, 通識(未分類)"
|
||||
print("{} {}".format(course['number'], course['name']))
|
||||
|
||||
with open("歷年課程資料/{}_output.json".format(YEAR), "w") as fp:
|
||||
json.dump(courses, fp, ensure_ascii=False)
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
year = input("年份: ")
|
||||
|
||||
getGeneralCourseData(year)
|
||||
curlDepartmentCourseTable(year)
|
||||
|
||||
print("\n\n=====================")
|
||||
print("未列入追蹤的通識課程")
|
||||
print("=====================\n")
|
||||
|
||||
for notIn in generalCourse:
|
||||
if "體育:" not in notIn[5]:
|
||||
print(" - 未列入追蹤的新通識課程: {}".format(notIn))
|
||||
while True:
|
||||
username = USERNAME
|
||||
password = PASSWORD
|
||||
if login(username, password):
|
||||
print("登入成功!")
|
||||
break
|
||||
else:
|
||||
print("登入失敗!")
|
||||
|
||||
curlDepartmentCourseTable(YEAR)
|
||||
extractDepartmentCourseTable(YEAR)
|
||||
updateGeneralCourse()
|
||||
@ -3,9 +3,9 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||
<meta name="description" content="" />
|
||||
<meta name="author" content="" />
|
||||
<title>暨大排課表</title>
|
||||
<meta name="description" content="你還在用紙筆或Excel在安排下學期的課表嗎?「暨大排課表」幫你篩選衝堂、科系分類、通識課程分類,讓你輕鬆排課表!" />
|
||||
<meta name="author" content="snsd0805" />
|
||||
<title>暨大排課表</title>
|
||||
<!-- Favicon-->
|
||||
<link rel="icon" type="image/x-icon" href="assets/img/favicon.ico" />
|
||||
<!-- Font Awesome icons (free version)-->
|
||||
|
||||
@ -8,35 +8,25 @@ var coursesList = {
|
||||
},
|
||||
methods: {
|
||||
'getTime': function (timeString) {
|
||||
if (timeString == null) {
|
||||
return ""
|
||||
}
|
||||
|
||||
ans = []
|
||||
number = ""
|
||||
for (var i of timeString) {
|
||||
if (i >= "0" && i <= "9") {
|
||||
number = i
|
||||
} else if (i >= "a" && i <= "z") {
|
||||
ans.push(number + i)
|
||||
}
|
||||
else {
|
||||
ans.push(timeString)
|
||||
break
|
||||
}
|
||||
}
|
||||
return ans
|
||||
let num;
|
||||
const timeRegex = new RegExp(/^\d[\da-z]*[a-z]$/);
|
||||
return timeRegex.test(timeString)
|
||||
? [...timeString].reduce((res, c) => {
|
||||
if (Number.isInteger(+c)) {
|
||||
num = c;
|
||||
return res;
|
||||
} else {
|
||||
return [...res, num + c];
|
||||
}
|
||||
}, [])
|
||||
: [];
|
||||
},
|
||||
'isOK': function (course) {
|
||||
var time = this.getTime(course.time)
|
||||
// console.log(course.name, " ", time)
|
||||
for (t of time) {
|
||||
for (st of this.selectedTime) {
|
||||
if (t == st)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
const isConflict = time.some((t) => this.selectedTime.includes(t))
|
||||
|
||||
return time.length && !isConflict
|
||||
},
|
||||
'log': function (name, data) {
|
||||
console.log(name, data)
|
||||
|
||||
@ -9,6 +9,7 @@ var mainWindow = {
|
||||
"user": "",
|
||||
'token': "",
|
||||
'is_print': false,
|
||||
'creditNum': 0,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@ -96,6 +97,14 @@ var mainWindow = {
|
||||
}).then(function (jsonData) {
|
||||
console.log(jsonData)
|
||||
main.selectCourses = JSON.parse(jsonData['data'])
|
||||
|
||||
var courseSet = new Set()
|
||||
for (var course of main.selectCourses) {
|
||||
if (!courseSet.has(course.number+course.class)) { // 用 courseID + 班別 判斷是否重複
|
||||
main.creditNum += parseFloat(course.credit)
|
||||
courseSet.add(course)
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(function (err) {
|
||||
alert("錯誤: " + err)
|
||||
@ -105,6 +114,12 @@ var mainWindow = {
|
||||
'saveCourseTable': function () {
|
||||
var main = this
|
||||
if (this.token != "") {
|
||||
filteredCourses = []
|
||||
for(var tempCourse of main.selectCourses){
|
||||
if(tempCourse.temp == false){
|
||||
filteredCourses.push(tempCourse);
|
||||
}
|
||||
}
|
||||
fetch('https://api.snsd0805.com/courseTable', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
@ -112,7 +127,7 @@ var mainWindow = {
|
||||
},
|
||||
body: JSON.stringify({
|
||||
'token': main.token,
|
||||
'data': main.selectCourses
|
||||
'data': filteredCourses
|
||||
})
|
||||
})
|
||||
.then(function (response) {
|
||||
@ -134,20 +149,18 @@ var mainWindow = {
|
||||
}
|
||||
},
|
||||
'getTime': function (timeString) {
|
||||
ans = []
|
||||
number = ""
|
||||
for (var i of timeString) {
|
||||
if (i >= "0" && i <= "9") {
|
||||
number = i
|
||||
} else if (i >= "a" && i <= "z") {
|
||||
ans.push(number + i)
|
||||
}
|
||||
else {
|
||||
ans.push(timeString)
|
||||
break
|
||||
}
|
||||
}
|
||||
return ans
|
||||
let num;
|
||||
const timeRegex = new RegExp(/^\d[\da-z]*[a-z]$/);
|
||||
return timeRegex.test(timeString)
|
||||
? [...timeString].reduce((res, c) => {
|
||||
if (Number.isInteger(+c)) {
|
||||
num = c;
|
||||
return res;
|
||||
} else {
|
||||
return [...res, num + c];
|
||||
}
|
||||
}, [])
|
||||
: [];
|
||||
},
|
||||
'select': function (department) {
|
||||
this.selectDepartment = department
|
||||
@ -163,9 +176,12 @@ var mainWindow = {
|
||||
'name': course.name,
|
||||
'temp': false,
|
||||
'number': course.number,
|
||||
'class': course.class
|
||||
'class': course.class,
|
||||
'credit': course.credit,
|
||||
'link': course.link
|
||||
})
|
||||
}
|
||||
this.creditNum += parseFloat(course.credit)
|
||||
},
|
||||
'removeCourse': function (course) {
|
||||
console.log("remove " + course.name)
|
||||
@ -174,6 +190,7 @@ var mainWindow = {
|
||||
this.selectCourses.splice(i, 1)
|
||||
}
|
||||
}
|
||||
this.creditNum -= parseFloat(course.credit)
|
||||
},
|
||||
'saveTemp': function (course) {
|
||||
if (course == null) {
|
||||
@ -275,6 +292,7 @@ var mainWindow = {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
<div class="row mx-auto mb-2">
|
||||
@ -299,7 +317,18 @@ var mainWindow = {
|
||||
>
|
||||
</course-anslist>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
已經選了 {{ creditNum }} 學分
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="col-lg-9 table-responsive " >
|
||||
<course-table
|
||||
@ -328,12 +357,11 @@ var mainWindow = {
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<ul>
|
||||
<li>已經更新為 1092 新課表(包含通識課分類)</li>
|
||||
<li>使用 Facebook API 儲存課表</li>
|
||||
<li>新增「下載圖檔」功能</li>
|
||||
<li>新增「分享課表」功能</li>
|
||||
<li>已經更新為 1101 新學期課表(包含通識課分類)</li>
|
||||
<li>有發現 Bug 可以到 <a href='https://github.com/snsd0805/NCNU_Course/issues'>GitHub</a> 發 issue 或 <a href='mailto: levi900227@gmail.com'>mail</a></li>
|
||||
<li>請善用「連接 Facebook」功能來儲存課表!</li>
|
||||
</ul>
|
||||
2021 01/23 更新
|
||||
2021 07/16 更新
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">我知道了</button>
|
||||
@ -353,7 +381,7 @@ var mainWindow = {
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
請複製以下網址給你的朋友,跟他分享你的課表<br><br>
|
||||
https://snsd0805.com/NCNU_Course/#/share/{{user.id}}
|
||||
https://course.snsd0805.com/#/share/{{user.id}}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">我知道了</button>
|
||||
@ -364,4 +392,4 @@ var mainWindow = {
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ var courseDiv = {
|
||||
template: `
|
||||
<div style='border: 5px #1abc9c solid; text-align: center;'>
|
||||
{{ course.name }}
|
||||
<a v-bind:href="course.link" target="_blank"><i class="fas fa-info-circle"></i></a>
|
||||
<button type="button"
|
||||
v-if="!is_shared"
|
||||
v-on:click="$emit('remove-course', course)"
|
||||
@ -54,7 +55,9 @@ var courseTable = {
|
||||
'name': c.name,
|
||||
'number': c.number,
|
||||
'class': c.class,
|
||||
'temp': c.temp
|
||||
'temp': c.temp,
|
||||
'credit': c.credit,
|
||||
'link': c.link
|
||||
}
|
||||
|
||||
if(c.time[0]==6 || c.time[0]==7){
|
||||
|
||||
20
ncnu-course-api.service
Normal file
20
ncnu-course-api.service
Normal file
@ -0,0 +1,20 @@
|
||||
[Unit]
|
||||
Description=NCNU-Course Python Backend API
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=python3 api.py
|
||||
Restart=always
|
||||
|
||||
WorkingDirectory=/var/www/html/NCNU_Course
|
||||
User=course
|
||||
|
||||
RestartSec=10s
|
||||
|
||||
StandardOutput=syslog
|
||||
StandardOutput=syslog
|
||||
SyslogIdentifier=ncnu-course
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
File diff suppressed because one or more lines are too long
1
歷年課程資料/1101_output.json
Normal file
1
歷年課程資料/1101_output.json
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user