iSJTU Interface#

pysjtu.client.Client is the main interface to the iSJTU API.

It is composed of multiple mixins, each of which provides a set of methods to access a specific part of the API.

Student ID#

Client.student_id#

Get the student id of the current session.

Example:

To get the student id of current user:

client.student_id
# 519027910001

Term Start Date#

Client.term_start_date#

Get the term start date for the current term.

Example:

To get the start date of current term:

client.term_start_date
# datetime.date(2019, 9, 9)

Schedule Query#

class pysjtu.client.api.schedule.ScheduleMixin#

Bases: BaseClient

schedule(year, term, **kwargs)#

Fetch your course schedule of specific year & term.

See pysjtu.session.Session.post() for more information about the keyword arguments.

Parameters:
  • year (int) – query year

  • term (int) – query term

Return type:

Results[ScheduleCourse]

Example:

To fetch your schedule of the first term in 2019, filter by criteria, and dig into details:

schedule = client.schedule(2019, 0)
# [<ScheduleCourse 军事理论 week=[range(9, 17)] day=1 time=range(1, 3)>, ...]
schedule.filter(time=[1, range(5, 7)], day=[2, range(4, 5)]))
# [<ScheduleCourse 线性代数 week=[range(1, 7), range(8, 17)] day=2 time=range(1, 3)>,
# <ScheduleCourse 线性代数 week=[7] day=2 time=range(1, 3)>,
# <ScheduleCourse 思想道德修养与法律基础 week=[range(1, 17)] day=2 time=range(6, 9)>,
# <ScheduleCourse 程序设计思想与方法(C++) week=[range(1, 16, 2)] day=4 time=range(1, 3)>]
schedule[0].name
# '军事理论'

Exam Query#

class pysjtu.client.api.exam.ExamMixin#

Bases: BaseClient

exam(year, term, **kwargs)#

Fetch your exams schedule of specific year & term.

See pysjtu.session.Session.post() for more information about the keyword arguments.

Parameters:
  • year (int) – query year

  • term (int) – query term

Return type:

Results[Exam]

Example:

To get your exams of the first term in 2019, filter by criteria, and dig into details:

exams = client.exam(2019, 0)
# [<Exam "2019-2020-1数学期中考" location=东上院509 datetime=2019-11-06(13:10-15:10)>, ...]
exams.filter(date=datetime.date(2019, 12, 31))
# [<Exam "2019-2020-1一专期末考(2019级)" location=东上院509 datetime=2019-12-31(08:00-10:00)>]
exams[0].name
# '2019-2020-1数学期中考'

Score Query#

class pysjtu.client.api.score.ScoreMixin#

Bases: BaseClient

score(year, term, **kwargs)#

Fetch your scores of specific year & term.

See pysjtu.session.Session.post() for more information about the keyword arguments.

Parameters:
  • year (int) – query year

  • term (int) – query term

Return type:

Scores

Example:

To get your exams of the first term in 2019, filter by criteria, and dig into details:

scores = client.score(2019, 0)
# [<Score 大学化学 score=xx credit=x.x gp=x.x>, ...>
scores.filter(gp=4)
# [<Score xxxxx score=91 credit=2.0 gp=4.0>, ...]
score = scores[0]
# <Score 大学化学 score=xx credit=x.x gp=x.x>
score.name
# '大学化学'
score_detail = score.detail
# [<ScoreFactor 平时(40.0%)=xx.x>, <ScoreFactor 期末(60.0%)=xx.x>]
score_detail[0].percentage
# 0.4

GPA Query#

class pysjtu.client.api.gpa.GPAMixin#

Bases: BaseClient

property default_gpa_query_params: GPAQueryParams#

Get default gpa query params defined by the website.

gpa(query_params, **kwargs)#

Query your GP & GPA and their rankings of specific year & term.

Warning

GPA calculation is done by the website, and this process often takes a long time.

It’s recommended to increase timeout to a larger value (e.g. 20s).

See Timeout Configuration for more details.

See pysjtu.session.Session.post() for more information about the keyword arguments.

Parameters:

query_params (GPAQueryParams) – parameters for this query. A default one can be fetched by reading property default_gpa_query_params.

Return type:

GPA

Example:

To fetch default GPA query parameters, change statistics scope and query GPA statistics:

query = client.default_gpa_query_params
# <GPAQueryParams {...}>
query.course_range = CourseRange.ALL
gpa = client.gpa(query)
# <GPA gp=98.9876543210 2/99 gpa=4.3 2/99>
gpa.gpa
# 4.3

College-Wide Course Search#

class pysjtu.client.api.course.CourseLibMixin#

Bases: BaseClient

query_courses(year, term, page_size=15, name=None, teacher=None, day_of_week=None, week=None, time_of_day=None, **kwargs)#

Query courses matching given criteria from the whole course lib of SJTU.

See pysjtu.session.Session.post() for more information about the keyword arguments.

Parameters:
  • year (int) – year in which target courses are given.

  • term (int) – term in which target courses are given.

  • page_size (int) – page size for result iteration.

  • name (Optional[str]) – (optional) Name (can be fuzzy) of target courses.

  • teacher (Optional[str]) – (optional) Teacher name of target courses.

  • day_of_week (Optional[list]) – (optional) Day of week of target courses.

  • week (Optional[list]) – (optional) Week of target courses.

  • time_of_day (Optional[list]) – (optional) Time of day of target courses.

Return type:

QueryResult[LibCourse]

Example:

To perform a college-wide course search:

courses = client.query_course(2019, 0, name="高等数学")
# <pysjtu.model.base.QueryResult object at 0x7fd46439ac50>
len(courses)
# 90
courses[-1]
# <LibCourse 高等数学I class_name=(2019-2020-1)-MA248-20>
courses[14:16]
# [<LibCourse 高等数学III class_name=(2019-2020-1)-MA172-1>, <LibCourse 高等数学IV class_name=(2019-2020-1)-MA173-1>]
list(courses)
# [<LibCourse 高等数学A1 class_name=(2019-2020-1)-VV156-1>, <LibCourse 高等数学B1 class_name=(2019-2020-1)-VV186-1>, ...]
courses[0].credit
# 4.0

Course Selection#

class pysjtu.client.api.selection.SelectionMixin#

Bases: BaseClient

property course_selection_sectors: List[SelectionSector]#

In iSJTU, courses are split into different sectors when selecting course. This property contains all available course sectors in this round of selection.

Example:

To select/drop a course:

# First, get course sectors
sectors = client.course_selection_sectors
sector = next(filter(lambda x: x == "主修", sectors))

# Then, fetch class list
classes = sector.classes
klass = next(filter(lambda x: x.class_name == "CS2305", classes))

# Finally, select/drop the class
while True:
    time.sleep(1)
    try:
        klass.register()    # or klass.drop()
        break
    except FullCapacityException:
        pass        # retry
    except Exception as e:
        raise e     # or handle other exceptions