1
|
|
|
# -*- coding: utf-8 -*-
|
2
|
|
|
from __future__ import absolute_import, unicode_literals
|
3
|
|
|
|
4
|
|
|
import inspect
|
5
|
|
|
import requests
|
6
|
|
|
|
7
|
|
|
from school_api.client.utils import get_time_list
|
8
|
|
|
from school_api.client.api.base import BaseSchoolApi
|
9
|
|
|
|
10
|
|
|
from school_api.client.api.utils import get_view_state_from_html
|
11
|
|
|
from school_api.client.login_management import LoginManagement
|
12
|
|
|
from school_api.session.memorystorage import MemoryStorage
|
13
|
|
|
from school_api.utils import to_text, ObjectDict
|
14
|
|
|
from school_api.config import URL_ENDPOINT, CLASS_TIME
|
15
|
|
|
|
16
|
|
|
|
17
|
|
|
def _is_api_endpoint(obj):
|
18
|
|
|
return isinstance(obj, BaseSchoolApi)
|
19
|
|
|
|
20
|
|
|
|
21
|
|
|
class BaseSchoolClient(object):
|
22
|
|
|
|
23
|
|
|
def __init__(self, url, **kwargs):
|
24
|
|
|
url = url.split('/default')[0] if url[-4:] == 'aspx' else url
|
25
|
|
|
class_time_list = kwargs.get('class_time_list') or CLASS_TIME
|
26
|
|
|
time_list = get_time_list(class_time_list)
|
27
|
|
|
|
28
|
|
|
self.school = {
|
29
|
|
|
'url': url,
|
30
|
|
|
'debug': kwargs.get('debug'),
|
31
|
|
|
'name': to_text(kwargs.get('name')),
|
32
|
|
|
'code': kwargs.get('code'),
|
33
|
|
|
'use_ex_handle': kwargs.get('use_ex_handle', True),
|
34
|
|
|
'exist_verify': kwargs.get('exist_verify', True),
|
35
|
|
|
'lan_url': kwargs.get('lan_url'),
|
36
|
|
|
'proxies': kwargs.get('proxies'),
|
37
|
|
|
'priority_proxy': kwargs.get('priority_proxy'),
|
38
|
|
|
'timeout': kwargs.get('timeout', 10),
|
39
|
|
|
'login_url': kwargs.get('login_url_path', '/default2.aspx'),
|
40
|
|
|
'url_endpoint': kwargs.get('url_endpoint') or URL_ENDPOINT,
|
41
|
|
|
'time_list': time_list
|
42
|
|
|
}
|
43
|
|
|
storage = kwargs.get('session', MemoryStorage)
|
44
|
|
|
self.session = storage(self.school['code'])
|
45
|
|
|
self.school = ObjectDict(self.school)
|
46
|
|
|
|
47
|
|
|
|
48
|
|
|
class BaseUserClient(LoginManagement):
|
49
|
|
|
"""docstring for BaseUserClient"""
|
50
|
|
|
|
51
|
|
|
_proxy = None
|
52
|
|
|
|
53
|
|
|
def __new__(cls, *args):
|
54
|
|
|
self = super(BaseUserClient, cls).__new__(cls)
|
55
|
|
|
api_endpoints = inspect.getmembers(self, _is_api_endpoint)
|
56
|
|
|
for name, api in api_endpoints:
|
57
|
|
|
api_cls = type(api)
|
58
|
|
|
api = api_cls(self)
|
59
|
|
|
setattr(self, name, api)
|
60
|
|
|
return self
|
61
|
|
|
|
62
|
|
|
def __init__(self, school, account, password, user_type):
|
63
|
|
|
self._http = requests.Session()
|
64
|
|
|
|
65
|
|
|
self.account = to_text(account)
|
66
|
|
|
self.password = password
|
67
|
|
|
self.user_type = user_type
|
68
|
|
|
self.school = school.school
|
69
|
|
|
self.base_url = self.school.url
|
70
|
|
|
self.session = school.session
|
71
|
|
|
|
72
|
|
|
self._http.headers.update({
|
73
|
|
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) '
|
74
|
|
|
'AppleWebKit/537.36 (KHTML, like Gecko) '
|
75
|
|
|
'Chrome/62.0.3202.89 Safari/537.36',
|
76
|
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
77
|
|
|
'Referer': self.base_url + self.school.login_url
|
78
|
|
|
})
|
79
|
|
|
if self.school.priority_proxy:
|
80
|
|
|
self.switch_proxy()
|
81
|
|
|
|
82
|
|
|
def _request(self, method, url_or_endpoint, **kwargs):
|
83
|
|
|
if not url_or_endpoint.startswith(('http://', 'https://')):
|
84
|
|
|
url = '{base}{endpoint}'.format(
|
85
|
|
|
base=self.base_url,
|
86
|
|
|
endpoint=url_or_endpoint
|
87
|
|
|
)
|
88
|
|
|
else:
|
89
|
|
|
url = url_or_endpoint
|
90
|
|
|
|
91
|
|
|
kwargs['timeout'] = kwargs.get('timeout', self.school.timeout)
|
92
|
|
|
res = self._http.request(
|
93
|
|
|
method=method,
|
94
|
|
|
url=url,
|
95
|
|
|
proxies=self._proxy,
|
96
|
|
|
**kwargs
|
97
|
|
|
)
|
98
|
|
|
return res
|
99
|
|
|
|
100
|
|
|
def get(self, url, **kwargs):
|
101
|
|
|
return self._request(
|
102
|
|
|
method='GET',
|
103
|
|
|
url_or_endpoint=url,
|
104
|
|
|
**kwargs
|
105
|
|
|
)
|
106
|
|
|
|
107
|
|
|
def post(self, url, **kwargs):
|
108
|
|
|
return self._request(
|
109
|
|
|
method='POST',
|
110
|
|
|
url_or_endpoint=url,
|
111
|
|
|
**kwargs
|
112
|
|
|
)
|
113
|
|
|
|
114
|
|
|
def head(self, url, **kwargs):
|
115
|
|
|
return self._request(
|
116
|
|
|
method='HEAD',
|
117
|
|
|
url_or_endpoint=url,
|
118
|
|
|
**kwargs
|
119
|
|
|
)
|
120
|
|
|
|
121
|
|
|
def switch_proxy(self):
|
122
|
|
|
""" 设置代理 """
|
123
|
|
|
self.base_url = self.school.lan_url or self.base_url
|
124
|
|
|
self._proxy = self.school.proxies
|
125
|
|
|
self._http.headers.update({
|
126
|
|
|
'Referer': self.base_url + self.school.login_url
|
127
|
|
|
})
|
128
|
|
|
|
129
|
|
|
if not self.school.priority_proxy:
|
130
|
|
|
# 检查是否有登录会话
|
131
|
|
|
return self._get_login_session()
|
132
|
|
|
|
133
|
|
|
self.school.priority_proxy = True
|
134
|
|
|
|
135
|
|
|
def get_view_state(self, url_suffix, **kwargs):
|
136
|
|
|
""" 获取页面 view_state 值"""
|
137
|
|
|
res = self.get(url_suffix, allow_redirects=False, **kwargs)
|
138
|
|
|
res.raise_for_status()
|
139
|
|
|
if res.status_code == 302:
|
140
|
|
|
raise requests.TooManyRedirects
|
141
|
|
|
|
142
|
|
|
return get_view_state_from_html(res.text)
|
143
|
|
|
|