示例#1
0
class NetPortalAPI:
    def __init__(self, language="EN"):
        self.request = HTTPRequest(URI('https://www.wnp.waseda.jp/portal',
                                       'portal.php'),
                                   encoding='euc-jp')
        self.request.set_dummy_headers()
        self.request.set_parameter('JavaCHK', 1)
        self.request.set_parameter('LOGINCHECK', 1)
        self.language = language
        self.set_language()
        self.logged = False
        self.logged_cnavi = False
        self._user_info = {}
        self.session_id_encode_key = None

    def set_language(self):
        self.request.set_parameter('HID_P14', self.language)

    @property
    def user_info(self):
        if not self.logged:
            raise NetPortalException(
                "Need to login to get user info from API.")
        return self._user_info

    def login(self, username, password):
        self.request.uri.url = 'portal.php'
        self.request.method = "GET"
        response = self.request.send()
        self.request.set_cookies(response.cookies)
        if not 'PHPSESSID' in response.cookies:
            raise NetPortalException("Could not get PHPSESSID")
        self.net_portal_sessid = response.cookies['PHPSESSID']
        self.request.set_parameter('PHPSESSID',
                                   response.cookies['PHPSESSID'].value)
        self.request.uri.url = 'portalLogin.php'
        response = self.request.send()
        self.request.set_cookies(response.cookies)
        if not 'PHP_Sessionid' in response.cookies:
            raise NetPortalException("Could not get PHP_Sessionid")

        self.request.uri.url = 'portal.php'
        self.request.remove_parameter('PHPSESSID')
        self.request.set_parameter('PHP_Sessionid',
                                   response.cookies['PHP_Sessionid'].value)
        self.request.set_parameter('loginid', username)
        self.request.set_parameter('passwd', password)
        self.request.method = "POST"
        response = self.request.send()

        # check if password was correct
        if not 'Admission_Key' in response.cookies:
            return False

        self.request.set_cookies(response.cookies)

        body = BeautifulSoup(response.get_body())
        link = body.find("frame", {'name': 'LeftMenu'})['src']
        self._get_left_menu_info(URI.parse(link, is_relative=True))
        self.logged = True
        return True

    def _get_left_menu_info(self, uri):
        # get left menu
        self.request.uri.url = uri.url
        self.request.reset_parameters()
        self.request.method = "GET"
        for (key, value) in uri.params.items():
            self.request.set_parameter(key, value)

        response = self.request.send()
        self.request.set_cookies(response.cookies)

        # parse left menu

        body = BeautifulSoup(response.get_body())

        # get hidden form with personal info
        form = body.find("form", {'name': 'LinkIndication'})
        self.request.reset_parameters()
        for field in form.find_all("input"):
            self.request.set_parameter(field['name'], field['value'])
            if field['name'] in info_input.keys():
                info_input[field['name']](field['value'], self._user_info)

        # get missing info from JS
        missing_info = [
            "LinkURL", "CateCode", "MenuCode", "UrlCode", "LogData",
            "MenuLinkName"
        ]
        reg = ".*?MenuLinkOpen\(" + (
            "\'(.*?)\'," *
            5) + "\'(.*?)\'\).*"  # regex for JS function call params -_-'
        # info written in the last script of the first table

        target_script = body.find("table").find_all("script")[-1]
        for line in str(target_script).splitlines():
            if "coursenavi/index3.php" in line:
                m = re.match(reg, line)
                if not m:
                    raise NetPortalException(
                        "Could not parse course navi link")
                # missing info captured in groups 1 to 6
                for (key, value) in zip(missing_info,
                                        [m.group(i) for i in range(1, 7)]):
                    self.request.set_parameter(
                        key.decode("utf-8"), value.decode("utf-8")
                    )  # BeautifulSoup encodes in utf by default
                break

        self.request.uri.url = "LogOutput.php"
        self.request.method = "POST"
        response = self.request.send()

        # prepare data to log to course navi
        self.request.set_cookies(response.cookies)
        body = BeautifulSoup(response.get_body())
        self.cnavi_data = {}
        for field in body.find_all("input"):
            self.cnavi_data[field['name']] = field['value']

    def login_cnavi(self):
        if not self.logged:
            raise NetPortalException("Need to login before login to cnavi")
        self.request.uri = URI('https://cnavi.waseda.jp',
                               'coursenavi/index2.php')
        self.request.method = "POST"
        self.request.set_parameters(self.cnavi_data)
        self.request.encoding = "utf-8"
        self.request.remove_cookie(
            "PHPSESSID")  # different PHPSESSID for this domain

        response = self.request.send()
        self.request.set_cookies(response.cookies)
        self.cnavi_data.clear()
        body = BeautifulSoup(response.get_body())

        for field in body.find_all("input"):
            self.cnavi_data[field['name']] = field['value']
        self.request.set_parameters(self.cnavi_data)
        self.request.uri.url = "index.php"

        self.logged_cnavi = True

    def get_all_subjects(self):
        subjects = {}
        for cat in ['attending', 'to_attend', 'attended']:
            subjects.update(self.get_subjects(cat))
        return subjects

    def get_subjects(self, subject_category='attending'):
        if not self.logged_cnavi:
            raise NetPortalException("Need to login to cnavi to get subjects")
        self.request.set_parameter('ControllerParameters', 'ZX14SubCon')
        self.request.set_parameter('hidListMode',
                                   subjects_category[subject_category])
        response = self.request.send()
        body = BeautifulSoup(response.get_body())
        subjects_container = body.find('div', {'id': 'wKTable'}).find("ul")
        ids = []
        folders = []
        for subject in subjects_container.find_all("li"):
            info = subject.find('p', {'class': 'w-col6'})
            ids.append(info.find('input', {'name': 'chkbox[]'})['value'])
            folders.append(
                info.find('input', {'name': 'folder_id[]'})['value'])

        subjects = {}
        # ids are in the form "yyyyIDIDIDID"
        # use IDIDIDID as dictionary key
        # zip with folders to iterate on all needed information
        for (k, y, f) in map(lambda (s, f): (s[4:], s[:4], f),
                             zip(ids, folders)):
            subjects.setdefault(k, {"folder_id": f, "years": []})
            subjects[k]["years"].append(y)

        return subjects
示例#2
0
class NetPortalAPI:
    def __init__(self, language="EN"):
        self.request = HTTPRequest(URI('https://www.wnp.waseda.jp/portal', 'portal.php'), encoding='euc-jp')
        self.request.set_dummy_headers()
        self.request.set_parameter('JavaCHK', 1)
        self.request.set_parameter('LOGINCHECK', 1)
        self.language = language
        self.set_language()
        self.logged = False
        self.logged_cnavi = False
        self._user_info = {}
        self.session_id_encode_key = None

    def set_language(self):
        self.request.set_parameter('HID_P14', self.language)

    @property
    def user_info(self):
        if not self.logged:
            raise NetPortalException("Need to login to get user info from API.")
        return self._user_info

    def login(self, username, password):
        self.request.uri.url = 'portal.php'
        self.request.method = "GET"
        response = self.request.send()
        self.request.set_cookies(response.cookies)
        if not 'PHPSESSID' in response.cookies:
            raise NetPortalException("Could not get PHPSESSID")
        self.net_portal_sessid = response.cookies['PHPSESSID']
        self.request.set_parameter('PHPSESSID', response.cookies['PHPSESSID'].value)
        self.request.uri.url = 'portalLogin.php'
        response = self.request.send()
        self.request.set_cookies(response.cookies)
        if not 'PHP_Sessionid' in response.cookies:
          raise NetPortalException("Could not get PHP_Sessionid")

        self.request.uri.url = 'portal.php'
        self.request.remove_parameter('PHPSESSID')
        self.request.set_parameter('PHP_Sessionid', response.cookies['PHP_Sessionid'].value)
        self.request.set_parameter('loginid', username)
        self.request.set_parameter('passwd', password)
        self.request.method = "POST"
        response = self.request.send()

        # check if password was correct
        if not 'Admission_Key' in response.cookies:
            return False

        self.request.set_cookies(response.cookies)

        body = BeautifulSoup(response.get_body())
        link = body.find("frame", {'name': 'LeftMenu'})['src']
        self._get_left_menu_info(URI.parse(link, is_relative=True))
        self.logged = True
        return True

    def _get_left_menu_info(self, uri):
        # get left menu
        self.request.uri.url = uri.url
        self.request.reset_parameters()
        self.request.method = "GET"
        for (key, value) in uri.params.items():
            self.request.set_parameter(key, value)

        response = self.request.send()
        self.request.set_cookies(response.cookies)

        # parse left menu

        body = BeautifulSoup(response.get_body())

        # get hidden form with personal info
        form = body.find("form", {'name': 'LinkIndication'})
        self.request.reset_parameters()
        for field in form.find_all("input"):
            self.request.set_parameter(field['name'], field['value'])
            if field['name'] in info_input.keys():
                info_input[field['name']](field['value'], self._user_info)

        # get missing info from JS
        missing_info = ["LinkURL", "CateCode", "MenuCode", "UrlCode", "LogData", "MenuLinkName"]
        reg = ".*?MenuLinkOpen\(" + ("\'(.*?)\'," * 5) + "\'(.*?)\'\).*"  # regex for JS function call params -_-'
        # info written in the last script of the first table

        target_script = body.find("table").find_all("script")[-1]
        for line in str(target_script).splitlines():
            if "coursenavi/index3.php" in line:
                m = re.match(reg, line)
                if not m:
                    raise NetPortalException("Could not parse course navi link")
                # missing info captured in groups 1 to 6
                for (key, value) in zip(missing_info, [m.group(i) for i in range(1, 7)]):
                    self.request.set_parameter(key.decode("utf-8"), value.decode("utf-8"))  # BeautifulSoup encodes in utf by default
                break

        self.request.uri.url = "LogOutput.php"
        self.request.method = "POST"
        response = self.request.send()

        # prepare data to log to course navi
        self.request.set_cookies(response.cookies)
        body = BeautifulSoup(response.get_body())
        self.cnavi_data = {}
        for field in body.find_all("input"):
            self.cnavi_data[field['name']] = field['value']

    def login_cnavi(self):
        if not self.logged:
            raise NetPortalException("Need to login before login to cnavi")
        self.request.uri = URI('https://cnavi.waseda.jp', 'coursenavi/index2.php')
        self.request.method = "POST"
        self.request.set_parameters(self.cnavi_data)
        self.request.encoding = "utf-8"
        self.request.remove_cookie("PHPSESSID")  # different PHPSESSID for this domain

        response = self.request.send()
        self.request.set_cookies(response.cookies)
        self.cnavi_data.clear()
        body = BeautifulSoup(response.get_body())

        for field in body.find_all("input"):
            self.cnavi_data[field['name']] = field['value']
        self.request.set_parameters(self.cnavi_data)
        self.request.uri.url = "index.php"

        self.logged_cnavi = True

    def get_all_subjects(self):
        subjects = {}
        for cat in ['attending', 'to_attend', 'attended']:
            subjects.update(self.get_subjects(cat))
        return subjects

    def get_subjects(self, subject_category='attending'):
        if not self.logged_cnavi:
            raise NetPortalException("Need to login to cnavi to get subjects")
        self.request.set_parameter('ControllerParameters', 'ZX14SubCon')
        self.request.set_parameter('hidListMode', subjects_category[subject_category])
        response = self.request.send()
        body = BeautifulSoup(response.get_body())
        subjects_container = body.find('div', {'id': 'wKTable'}).find("ul")
        ids = []
        folders = []
        for subject in subjects_container.find_all("li"):
            info = subject.find('p', {'class': 'w-col6'})
            ids.append(info.find('input', {'name': 'chkbox[]'})['value'])
            folders.append(info.find('input', {'name': 'folder_id[]'})['value'])

        subjects = {}
        # ids are in the form "yyyyIDIDIDID"
        # use IDIDIDID as dictionary key
        # zip with folders to iterate on all needed information
        for (k, y, f) in map(lambda (s, f): (s[4:], s[:4], f), zip(ids, folders)):
            subjects.setdefault(k, {"folder_id": f, "years": []})
            subjects[k]["years"].append(y)

        return subjects