曾神在群里分享了一个开源项目 《JMU-json2ics》 。可以用我们学校的课表生成 ics日历 文件。
这个小项目引发了我的兴趣,遂决定阅读一遍源码,顺便复习下python语法。
第一部分:json文件结构解读
总体结构
课程信息主要保存在 ”adminclass“ 条录下
{
"studentTableVm": {
"id": 22471,
"name": "陈煜晗", //学生姓名
"code": "2020*****104",//学生学号
"grade": "2020", //年级
"department": "计算机工程学院", //学院
"major": "计算机科学与技术", //专业
"adminclass": "计算2014",//班级
"credits": 25.75, //学分
"totalRetakeCredits": 0, //已确认学分
"activities": [...], //!!!课程列表!!!。
"lessonSearchVms": [...],//下列不表。
"practiceLessonSearchVms": [...],
"arrangedLessonSearchVms":[...],
"timeTableLayout": {"id": 1...},
"courseTablePrintConfigs": [...],
"lessonNamePrint": false
}
}
课程信息 activities
以列表形式保存课程信息。
对于每一个课程,以字典形式保存基本信息
{
"lessonId": 62937, //课程代号?
"lessonCode": "D000607-0006",//课程编号
"lessonName": "21-22-01大学英语三级综合06", //课程班名称
"courseCode": "D000607",
"courseName": "大学英语 (3)", //课程名称
"weeksStr": "5~13(单)", //上课周次描述信息
"weekIndexes": [5, 7, 9, 11, 13],//上课周次
"room": "汉水0306",//教室
"building": "庄汉水楼",//教学楼
"campus": "主校区",//教学校区
"weekday": 1,//周几上课
"startUnit": 7,//第几节课开始
"endUnit": 8,//第几节课结束
"lessonRemark": null,//重修
"teachers": ["林瑞芳"],//授课教师
"courseType": null,//课程类型 默认?
"credits": 2.5,//学分
"periodInfo": {"total": 40...},//进阶信息,下表。
"stdCount": 66,//学生人数
"limitCount": 80,//限制人数
"tableShowAdminclass": [...],
"adminclassVms": [...],
"activityRoomTypeSign": null,
"activityRoomTimesOrUnits": null,
"taskPeopleNum": null
},
”periodInfo“ 是课程的进阶信息。 这里没有用到,仅作猜测,不保证正确性。
"periodInfo": {
"total": 40,
"weeks": 16,
"theory": 40,//课时
"theoryUnit": "HOUR",//课时单位
"requireTheory": 40,//要求课时
"practice": null, //实践课时
"practiceUnit": null,//实践课时单位
"requirePractice": null,//需要实践课时
"focusPractice": null,//需要实践课时单位
"focusPracticeUnit": null,
"dispersedPractice": null,
"test": null,//小测
"testUnit": null,//小测单位
"requireTest": null,//要求小测
"experiment": null,//实验课时
"experimentUnit": null,//实验课时单位
"requireExperiment": null,//要求实验课时
"machine": null,//机器
"machineUnit": null,//机器单位
"requireMachine": null,//需要机器单位 (上机?)
"design": null,//课程设计课时
"designUnit": null,//课程设计课时单位
"requireDesign": null,//要求课程设计课时
"periodsPerWeek": 0, //每周周期
"extra": null,//额外课时
"extraUnit": null,//额外课时单位
"requireExtra": null//要求额外课时
},
第二部分 :《JMU-json2ics》源码解读
主程序
def getInformation(json_data):
return json_data["studentTableVm"]["name"], json_data["studentTableVm"]["id"], json_data["studentTableVm"]["grade"], \
json_data["studentTableVm"]["major"], json_data["studentTableVm"]["adminclass"]
def main():
first_day_date_str = '2021-09-06' #开学日期。
time_zone = pytz.timezone('Asia/Shanghai') #更改时区为亚洲/上海
# 保存日历信息, Calendar 是常见的日历类。
calendar = Calendar()
#以UTF-8编码打开json文件。
with open('data1.json', encoding='utf-8') as f:
#读取json文件信息,以字典形式保存在json_data中
json_data = json.load(f)
#依次获取 姓名、学号、年级、专业、班级
name, studentId, grade, major, class_name = getInformation(json_data)
#读取课程列表
courseList = json_data["studentTableVm"]["activities"]
for course in courseList:... #(下接)
遍历课程
get_course_take_time
# 返回上课时间
def get_course_take_time(course_time):
# 第1、2节课8:0:0 - 9:35:0 以此类推。
course_time_table = {'12': [[8, 0, 0], [9, 35, 0]],
'34': [[10, 5, 0], [11, 40, 0]],
'14': [[8, 0, 0], [11, 40, 0]],
'56': [[14, 0, 0], [15, 35, 0]],
'78': [[15, 55, 0], [17, 30, 0]],
'58': [[14, 0, 0], [17, 30, 0]],
'910': [[19, 0, 0], [20, 35, 0]],
'911': [[19, 0, 0], [21, 25, 0]]}
return course_time_table[course_time][0], course_time_table[course_time][1]
for course in courseList:
# 课程在星期几
course_in_day_of_week = int(course['weekday'])
# 课程在第几周(列表形式)
course_take_weeks = list(course['weekIndexes'])
# 课程开始时间、结束时间
course_begin_time, course_end_time = get_course_take_time(
"{}{}".format(course['startUnit'], course['endUnit']))
# 遍历上课周次
for week in course_take_weeks:...#(下接)
#生成 (class_name)-(name).ics文件
output_file_name = '{} - {}.ics'.format(class_name, name)
output_file = open(output_file_name, 'wb')
#将calendar中的信息写入文件
output_file.write(calendar.to_ical())
output_file.close()
遍历课程的每一个周次
get_course_date
# 返回上课的日期
def get_course_date(first_day_date_str, course_in_day_of_week, which_week):
first_day_date = datetime.datetime.strptime(
first_day_date_str, r'%Y-%m-%d')
return first_day_date + datetime.timedelta(days=(which_week - 1) * 7 + (course_in_day_of_week - 1))
for week in course_take_weeks:
course_date = get_course_date(first_day_date_str, course_in_day_of_week, week)
# 注意这是icalendar中的Event
# 创建一个事件(课程)
event = Event()
# 添加课程概述,这里只添加了课程名称
event.add('summary', course['courseName'])
#添加课程开始时间
event.add('dtstart',
datetime.datetime(course_date.year, course_date.month, course_date.day, course_begin_time[0],
course_begin_time[1], course_begin_time[2], tzinfo=time_zone))
#添加课程结束时间
event.add('dtend',
datetime.datetime(course_date.year, course_date.month, course_date.day, course_end_time[0],
course_end_time[1], course_end_time[2], tzinfo=time_zone))
#添加触发事件时间
event.add('dtstamp',
datetime.datetime(course_date.year, course_date.month, course_date.day, course_begin_time[0],
course_begin_time[1], course_begin_time[2], tzinfo=time_zone))
# 添加课程地点
event.add('location', course['room'])
# 将事件添加到日历中
calendar.add_component(event)
完整源码及项目地址
源码
# -*- coding:utf-8 -*-
import requests
from icalendar import Calendar, Event
import pytz
import datetime
import hashlib
import os
import re
# 支持json
import json
# 返回上课的日期
def get_course_date(first_day_date_str, course_in_day_of_week, which_week):
first_day_date = datetime.datetime.strptime(
first_day_date_str, r'%Y-%m-%d')
return first_day_date + datetime.timedelta(days=(which_week - 1) * 7 + (course_in_day_of_week - 1))
# 返回上课时间
def get_course_take_time(course_time):
# 第1、2节课8:0:0 - 9:35:0 以此类推。
course_time_table = {'12': [[8, 0, 0], [9, 35, 0]],
'34': [[10, 5, 0], [11, 40, 0]],
'14': [[8, 0, 0], [11, 40, 0]],
'56': [[14, 0, 0], [15, 35, 0]],
'78': [[15, 55, 0], [17, 30, 0]],
'58': [[14, 0, 0], [17, 30, 0]],
'910': [[19, 0, 0], [20, 35, 0]],
'911': [[19, 0, 0], [21, 25, 0]]}
return course_time_table[course_time][0], course_time_table[course_time][1]
def getInformation(json_data):
return json_data["studentTableVm"]["name"], json_data["studentTableVm"]["id"], json_data["studentTableVm"]["grade"], \
json_data["studentTableVm"]["major"], json_data["studentTableVm"]["adminclass"]
def main():
first_day_date_str = '2021-09-06'
time_zone = pytz.timezone('Asia/Shanghai')
# 保存日历信息
calendar = Calendar()
# 初始化?
calendar.add('prodid', '-//My calendar product//mxm.dk//')
calendar.add('version', '2.0')
with open('data1.json', encoding='utf-8') as f:
json_data = json.load(f)
name, studentId, grade, major, class_name = getInformation(json_data)
courseList = json_data["studentTableVm"]["activities"]
print(type(courseList))
for course in courseList:
# 课程在星期几
course_in_day_of_week = int(course['weekday'])
# 课程在第几周(列表形式)
course_take_weeks = list(course['weekIndexes'])
# 课程开始时间、结束时间
course_begin_time, course_end_time = get_course_take_time(
"{}{}".format(course['startUnit'], course['endUnit']))
# 遍历上课周次
for week in course_take_weeks:
course_date = get_course_date(first_day_date_str, course_in_day_of_week, week)
event = Event()
event.add('summary', course['courseName'])
event.add('dtstart',
datetime.datetime(course_date.year, course_date.month, course_date.day, course_begin_time[0],
course_begin_time[1], course_begin_time[2], tzinfo=time_zone))
event.add('dtend',
datetime.datetime(course_date.year, course_date.month, course_date.day, course_end_time[0],
course_end_time[1], course_end_time[2], tzinfo=time_zone))
event.add('dtstamp',
datetime.datetime(course_date.year, course_date.month, course_date.day, course_begin_time[0],
course_begin_time[1], course_begin_time[2], tzinfo=time_zone))
event.add('location', course['room'])
calendar.add_component(event)
output_file_name = '{} - {}.ics'.format(class_name, name)
output_file = open(output_file_name, 'wb')
output_file.write(calendar.to_ical())
output_file.close()
if __name__ == '__main__':
main()