Last active
October 24, 2019 14:50
-
-
Save Gowee/54cbef455465236ef31a002f602bd665 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/dev python3 | |
# -*- coding: utf-8 -*- | |
import requests | |
import json | |
from ics import Calendar, Event | |
import arrow | |
from uuid import uuid4 | |
# Below are your credentials for log-in. | |
username = "222010000000000" | |
password = "123456" | |
# Below are the school year and the semester of which the program should get timetable. | |
school_year = 2016 | |
semester = 1 | |
# Change the first school week to the first week of certain semester you want below: | |
first_school_week = arrow.get("2016-09-05T00:00:00.000+08:00").span('week') | |
description_template = \ | |
""" | |
课程:{course_title} {course_type} | |
教师:{teacher_name}({teacher_title}) | |
地点:{campus} {location} | |
节次:{course_span} {course_nth_day_zh} {course_session} | |
备注:{nth_week} | |
""" | |
swu_urp = requests.session() | |
urp_url = "http://urp.swu.edu.cn" | |
oaa_portal_url = "http://jw.swu.edu.cn" | |
host = "goweatswu.cn" | |
daily_schedule = { # format: hh:mm:ss | |
# morning | |
1: {'begin': "08:00:00", 'end': "08:40:00"}, | |
2: {'begin': "08:50:00", 'end': "09:30:00"}, | |
3: {'begin': "09:40:00", 'end': "10:20:00"}, | |
4: {'begin': "10:40:00", 'end': "11:20:00"}, | |
5: {'begin': "11:30:00", 'end': "12:10:00"}, | |
# noon | |
6: {'begin': "08:00:00", 'end': "08:40:00"}, | |
7: {'begin': "08:00:00", 'end': "08:40:00"}, | |
# afternoon | |
8: {'begin': "14:30:00", 'end': "15:10:00"}, | |
9: {'begin': "15:20:00", 'end': "16:00:00"}, | |
10: {'begin': "16:10:00", 'end': "16:50:00"}, | |
11: {'begin': "17:00:00", 'end': "17:40:00"}, | |
# evening | |
12: {'begin': "19:00:00", 'end': "19:40:00"}, | |
13: {'begin': "19:50:00", 'end': "20:30:00"}, | |
14: {'begin': "20:40:00", 'end': "21:20:00"} | |
} | |
# TODO: Exclude all lessons during holidays, here should be holidays list. | |
holidays = { | |
} | |
semesters = {1: 3, 2: 12, 3: 16} | |
def gen_uid(): | |
return str(uuid4()) + "@" + host | |
if "handleLoginSuccessed" not in swu_urp.post(urp_url + "/userPasswordValidate.portal", data={ | |
"Login.Token1": username, | |
"Login.Token2": password, | |
"goto": urp_url + "/loginSuccess.portal", | |
"gotoOnFail": urp_url + "/loginFailure.portal" | |
}).text: | |
exit("Failed to login URP") | |
swu_urp.get(oaa_portal_url + "/jwglxt/idstar/index.jsp") | |
payload = { | |
"xnm": school_year, | |
"xqm": semesters[semester] | |
} | |
raw_timetable = json.loads(swu_urp.post( | |
oaa_portal_url + "/jwglxt/kbcx/xskbcx_cxXsKb.html?gnmkdmKey=N253508&sessionUserKey=" + username, data=payload).text) | |
timetable = Calendar(creator="swucalgen-build-20160611@" + host) | |
for lesson in raw_timetable['kbList']: | |
# generate list of weeks | |
weeks = [] | |
for week_range in lesson['zcd'].split(","): | |
if len(week_range.split("(")) == 2: | |
weeks += [n for n in | |
range(int(week_range.split("-")[0]), int(week_range.split("-")[1].split("(")[0].strip("周")) + 1) | |
if n % 2 == (1 if week_range.split("(")[1].strip(")") == "单" else 0)] | |
else: | |
weeks += list(range(int(week_range.split("-")[0]), int(week_range.split("-")[1].strip("周")) + 1))\ | |
if "-" in week_range else [int(week_range.strip("周"))] | |
for nth_week in weeks: | |
# lesson beginning time | |
daily_offset = daily_schedule[int(lesson['jcor'].split("-")[0])] | |
daily_offset = { | |
'hours': int(daily_offset['begin'][0:2]), | |
'minutes': int(daily_offset['begin'][3:5]), | |
'seconds': int(daily_offset['begin'][6:8]) | |
} | |
lesson_begin = first_school_week[0].replace(weeks=nth_week - 1, days=int(lesson['xqj']) - 1, **daily_offset) | |
# lesson ending time | |
daily_offset = daily_schedule[int(lesson['jcor'].split("-")[1])] | |
daily_offset = { | |
'hours': int(daily_offset['end'][0:2]), | |
'minutes': int(daily_offset['end'][3:5]), | |
'seconds': int(daily_offset['end'][6:8]) | |
} | |
lesson_end = first_school_week[0].replace(weeks=nth_week - 1, days=int(lesson['xqj']) - 1, **daily_offset) | |
metadata = { | |
'course_title': lesson['kcmc'], | |
'course_type': lesson['xslxbj'], | |
'course_span': lesson['zcd'], | |
'course_session': lesson['jc'], | |
'course_nth_day': lesson['xqj'], | |
'course_nth_day_zh': ["星期" + ["一", "二", "三", "四", "五", "六", "日"][n] for n in range(0, 7)][int(lesson['xqj']) - 1], | |
'teacher_name': lesson['xm'], | |
'teacher_title': lesson['zcmc'] if 'zcmc' in lesson else "无职称", | |
'campus': lesson['xqmc'], | |
'location': lesson['cdmc'], | |
'nth_week': "此时为第 " + str(nth_week) + " 周" | |
} | |
event = Event(lesson['kcmc'], lesson_begin, lesson_end, None, gen_uid(), | |
description_template.format_map(metadata), arrow.utcnow(), lesson['xqmc'] + " " + lesson['cdmc']) | |
timetable.events.append(event) | |
with open("./out.ics", "w", encoding="utf-8") as ics: | |
ics.writelines(list(timetable)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
使用指引:
说明:这是一个用以抓取 SWU 正方教务系统个人课表并以之生成 iCal 文件以便于导入 Calendar 应用的 Python 脚本。
pip3 install arrow ics
username = "学号"
password = "密码"
python Timetable2iCal_SWU.py
./out.ics
通常需要先为本课程表新建一个行事历(Calendar)以便管理,也可将其直接导入至主行事历中;一般操作方法为:在对应应用中选择“导入 iCal 文件”,而后选中本程序生成的 out.ics 文件导入即可;具体导入方法请自行搜索。