Created
January 29, 2018 20:58
-
-
Save ksqsf/b1d5e16386ae7d45e3d8f296bcc0df71 to your computer and use it in GitHub Desktop.
USTC Web services
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
""" | |
the USTC module | |
NOTE: this is an incomplete framework! extend it as you like. | |
PS: don't expect to receive updates or changes from me! this is not intended to be published anyway. :-p | |
""" | |
from bs4 import BeautifulSoup | |
import requests | |
class Passport: | |
""" | |
USTC Passport | |
1. GET USTC_LOGIN and obtain the CSRF token | |
2. Construct a form and POST it to USTC_LOGIN | |
3. Get cookies `laravel_session` and `ucas_TGC_2015` | |
""" | |
LOGIN_URL = "https://passport.ustc.edu.cn/login" | |
def __init__(self, student_id: str, password: str): | |
# Query a token | |
res = requests.get(Passport.LOGIN_URL) | |
cookies = res.cookies | |
soup = BeautifulSoup(res.text, 'html.parser') | |
token = soup.form.input['value'] | |
# Login | |
payload = {'_token': token, 'login': student_id, 'password': password, 'button': '登录'} | |
res = requests.post(Passport.LOGIN_URL, data=payload, cookies=cookies) | |
# Save the cookies for future use | |
self.cookies = res.cookies | |
# Check if succeeded | |
if res.text.find('成功') == -1: | |
raise RuntimeError("Couldn't not log into Passport") | |
class MIS: | |
""" | |
USTC MIS | |
1. GET USTC_MIS_LOGIN with appropriate cookies | |
2. Cookie `JSESSIONID` returned | |
""" | |
LOGIN_URL = "https://passport.ustc.edu.cn/login?service=http%3A%2F%2Fmis.teach.ustc.edu.cn/casLogin.do" | |
GRADES_URL = "http://mis.teach.ustc.edu.cn/querycjxx.do" | |
def __init__(self, passport: Passport): | |
res = requests.get(MIS.LOGIN_URL, cookies=passport.cookies) | |
self.cookies = res.cookies | |
def courses(self, semester: str): | |
""" | |
Query courses you selected for a specific semester. Semester is a string in the format | |
`'XXXXX'`, where `X` is a digit. The first 4 digits stand for the year, and the last digit | |
stands for the specific semester, which can be 1 (Fall), 2 (Spring) or 3 (Summer). | |
""" | |
raise NotImplementedError() | |
def grades(self): | |
""" | |
Query your grades. | |
Surprisingly, GET request is sufficient. HTML contents (!) are returned, so we must parse | |
them into machine-readable format, ie. dictionary. | |
@return as {total_credits, obtained_credits, not_obtained_credits, failed_credits, GPA, | |
average, weighted_average, [{semester, number, name, type, grade, credits}]} | |
""" | |
res = requests.get(MIS.GRADES_URL, cookies=self.cookies) | |
soup = BeautifulSoup(res.text, 'html.parser') | |
general_info = soup.tr.find_all() | |
course_info = soup.find_all('table')[2].find_all('tr') | |
ret = dict() | |
ret['total_credits'] = float(general_info[1].text) | |
ret['obtained_credits'] = float(general_info[3].text) | |
ret['not_obtained_credits'] = float(general_info[5].text) | |
ret['failed_credits'] = float(general_info[7].text) | |
ret['GPA'] = float(general_info[9].text) | |
ret['average'] = float(general_info[11].text) | |
ret['weighted_average'] = float(general_info[13].text) | |
courses = [] | |
for course in course_info[:-1]: # the last line is empty | |
cols = course.find_all('td') | |
courses.append({'semester': cols[0].text, 'number': cols[1].text, 'name': cols[2].text, | |
'type': cols[3].text, 'grade': cols[4].text, 'credits': cols[5].text}) | |
ret['courses'] = courses | |
return ret | |
def main(): | |
"Shut up." | |
passport = Passport('你的学号', '你的密码') | |
mis = MIS(passport) | |
print(mis.grades()) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment