school_api.client.api.login.Login.get_login()   C
last analyzed

Complexity

Conditions 11

Size

Total Lines 39
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 27
nop 3
dl 0
loc 39
rs 5.4
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like school_api.client.api.login.Login.get_login() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
# -*- coding: utf-8 -*-
2
from __future__ import absolute_import, unicode_literals
3
4
from requests import RequestException, TooManyRedirects
5
from six.moves.urllib import parse
6
7
from school_api.check_code import CHECK_CODE
8
from school_api.client.api.base import BaseSchoolApi
9
from school_api.client.api.utils import get_alert_tip, get_view_state_from_html
10
from school_api.exceptions import IdentityException, CheckCodeException, LoginException, \
11
    OtherException
12
from school_api.utils import to_binary, to_text
13
14
15
class Login(BaseSchoolApi):
16
    ''' 登录模块 '''
17
18
    def get_login(self, school, **kwargs):
19
        ''' 登录入口 与 异常处理 '''
20
        args = (school.login_url, school.exist_verify)
21
        try:
22
            res = self._get_api(*args, **kwargs)
23
        except OtherException as reqe:
24
            raise LoginException(self.school_code, to_text(str(reqe)))
25
26
        except RequestException:
27
            if school.proxies and not self.user.proxy_state:
28
                # 使用内网代理
29
                proxy_session = self._switch_proxy()
30
                if proxy_session:
31
                    # 存在内网代理会话
32
                    return True
33
                try:
34
                    res = self._get_api(*args, **kwargs)
35
                except RequestException:
36
                    raise LoginException(self.school_code, '教务系统异常,切用代理登录失败')
37
            else:
38
39
                if self.user.proxy_state:
40
                    raise LoginException(self.school_code, '教务系统异常,使用代理登录失败')
41
                else:
42
                    raise LoginException(self.school_code, '教务系统外网异常')
43
44
        # 处理登录结果
45
        try:
46
            self._handle_login_result(res)
47
        except CheckCodeException:
48
            try:
49
                # 验证码错误时,再次登录
50
                res = self._get_api(*args, **kwargs)
51
            except RequestException:
52
                raise LoginException(self.school_code, '教务系统请求异常')
53
            else:
54
                self._handle_login_result(res)
55
56
        return True
57
58
    def _handle_login_result(self, res):
59
        ''' 处理页面弹框信息 '''
60
        if res is True:
61
            # 登录成功
62
            return
63
        tip = get_alert_tip(res.text)
64
        if tip:
65
            if tip == '验证码不正确!!':
66
                raise CheckCodeException(self.school_code, tip)
67
            raise IdentityException(self.school_code, tip)
68
        raise LoginException(self.school_code, '教务系统请求异常')
69
70
    def _get_login_payload(self, login_url, **kwargs):
71
        ''' 获取登录页面的 请求参数'''
72
        try:
73
            kwargs['timeout'] = 3
74
            res = self._get(login_url, **kwargs)
75
        except TooManyRedirects as reqe:
76
            res = self._get(reqe.response.headers["Location"], **kwargs)
77
78
        except RequestException:
79
            # 首次请求可能出现 Connection aborted
80
            res = self._get(login_url, **kwargs)
81
82
        url_info = res.url.split(login_url)[0].split('/(')
83
        if len(url_info) == 2:
84
            self._update_url_token('/(' + url_info[1])
85
86
        view_state = get_view_state_from_html(res.text)
87
        return {'__VIEWSTATE': view_state}
88
89
    def _get_api(self, login_url, exist_verify, **kwargs):
90
        # 登录请求
91
        code = ''
92
        login_types = ['学生', '教师', '部门']
93
        login_payload = self._get_login_payload(login_url, **kwargs)
94
        if exist_verify:
95
            res = self._get('/CheckCode.aspx')
96
            if res.content[:7] != to_binary('GIF89aH'):
97
                raise CheckCodeException(self.school_code, "验证码获取失败")
98
            code = CHECK_CODE.verify(res.content)
99
100
        account = self.user.account.encode('gb2312')
101
        payload = {
102
            'txtUserName': account,
103
            'TextBox1': account,
104
            'TextBox2': self.user.password,
105
            'TextBox3': code,
106
            'txtSecretCode': code,
107
            'RadioButtonList1': login_types[self.user.user_type].encode('gb2312'),
108
            'Button1': ' 登 录 '.encode('gb2312')
109
        }
110
        payload.update(login_payload)
111
        try:
112
            res = self._post(login_url, data=payload, **kwargs)
113
        except TooManyRedirects:
114
            # 302跳转 代表登录成功
115
            return True
116
        return res
117
118
    def check_session(self):
119
        """ 检查登陆会话是否有效 """
120
        account = parse.quote(self.user.account.encode('gb2312'))
121
        try:
122
            self._head(self.school_url['HOME_URL'] + account)
123
        except RequestException:
124
            return False
125
126
        return True
127