Skip to content

Instantly share code, notes, and snippets.

@Gowee
Last active October 24, 2019 14:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Gowee/54cbef455465236ef31a002f602bd665 to your computer and use it in GitHub Desktop.
Save Gowee/54cbef455465236ef31a002f602bd665 to your computer and use it in GitHub Desktop.
#!/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))
@Gowee
Copy link
Author

Gowee commented Jun 11, 2016

使用指引:

说明:这是一个用以抓取 SWU 正方教务系统个人课表并以之生成 iCal 文件以便于导入 Calendar 应用的 Python 脚本。

  1. 运行环境: Python 3.5
  2. 安装依赖包: arrow, ics
  • pip3 install arrow ics
    1. 修改参数(在脚本中直接修改即可):
  • username = "学号"
  • password = "密码"
    1. 运行:
  • python Timetable2iCal_SWU.py
    1. 获取 iCal 文件:
  • 输出文件为:./out.ics
    1. 导入 Calendar 应用:
  • 推荐应用:
    • Google Calendar (Web or for iOS, Android)
    • Sunrise Calendar (Web or for Mac OS, iOS, Android)
    • Microsoft Outlook (Web or for UWP, Android, iOS)
    • 中华农历 (for Android)
    • 小米日历 (for Andorid)
    • iCloud (Web or for iOS, MacOS)
    • GNOME Calendar (for Linux)
  • 导入 iCal 文件:
    通常需要先为本课程表新建一个行事历(Calendar)以便管理,也可将其直接导入至主行事历中;一般操作方法为:在对应应用中选择“导入 iCal 文件”,而后选中本程序生成的 out.ics 文件导入即可;具体导入方法请自行搜索。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment