Passed
Push — master ( 7f7b6b...455dbe )
by dai
02:53
created

school_api.client.api.place_schedule   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 124
Duplicated Lines 87.9 %

Importance

Changes 0
Metric Value
wmc 23
eloc 95
dl 109
loc 124
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
C PlaceSchedule.get_schedule() 43 43 10
A PlaceSchedule._get_payload() 26 26 4
A PlaceSchedule._update_payload() 7 7 2
B PlaceSchedule._get_api() 26 26 7

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
# -*- coding: utf-8 -*-
0 ignored issues
show
Coding Style introduced by
This module should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
2
from __future__ import absolute_import, unicode_literals
3
4
import six.moves.urllib.parse as urlparse
5
6
from bs4 import BeautifulSoup
7
from requests import RequestException
8
9
from school_api.client.api.base import BaseSchoolApi
10
from school_api.client.api.utils.schedule_parse import ScheduleParse
11
from school_api.client.utils import ScheduleType
12
from school_api.exceptions import ScheduleException
13
14
15 View Code Duplication
class PlaceSchedule(BaseSchoolApi):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
Coding Style introduced by
This class should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
Unused Code introduced by
The variable __class__ seems to be unused.
Loading history...
16
    schedule_url = None
17
    payload = None
18
19
    def get_schedule(self, campus_list=None, **kwargs):
20
        ''' 课表信息 获取入口
21
        返回一个生成器,生成器一旦报错则将退出:https://codeday.me/bug/20180125/124136.html
22
        除了解析异常其他报错均不抛出
23
        '''
24
        self.schedule_url = self.school_url['PLACE_SCHEDULE_URL'] + \
25
            urlparse.quote(self.account.encode('gb2312'))
26
27
        if not self._update_payload(**kwargs):
28
            yield {'error': "获取教学场地课表失败"}
29
        else:
30
            # 遍历校区
31
            for campus in self.payload['campus_list']:
32
                if campus_list and campus["name"] not in campus_list:
33
                    continue
34
                if not self._update_payload(campus, **kwargs):
35
                    continue
36
                # 遍历教室类别
37
                for classroom_type in self.payload['classroom_type_list']:
38
                    if not self._update_payload(campus, classroom_type=classroom_type, **kwargs):
39
                        continue
40
                    # 遍历教室名称
41
                    for classroom_name in self.payload['classroom_name_list']:
42
                        try:
43
                            res = self._get_api(
44
                                campus, classroom_type=classroom_type,
45
                                classroom_name=classroom_name, **kwargs)
46
                        except ScheduleException:
47
                            continue
48
49
                        schedule = ScheduleParse(
50
                            res.content.decode('GB18030'),
51
                            self.time_list,
52
                            ScheduleType.CLASS
53
                        ).get_schedule_dict()
54
55
                        data = {
56
                            "campus": campus["name"],
57
                            "classroom_type": classroom_type["name"],
58
                            "classroom_name": classroom_name["name"]
59
                        }
60
                        data.update(schedule)
61
                        yield data
62
63
    def _get_api(self, campus=None, **kwargs):
64
        """ 请求函数 """
65
        if self.payload and campus:
66
            classroom_type = kwargs.pop('classroom_type', None)
67
            classroom_name = kwargs.pop('classroom_name', None)
68
            data = {
69
                "Button1": "",
70
                "xq": self.payload['schedule_term'],
71
                "xn": self.payload['schedule_year'],
72
                "ddlXq": campus["value"],
73
                "ddlJslb": classroom_type["value"].encode('gb2312') if classroom_type else '',
74
                "ddlJsmc": classroom_name["value"].encode('gb2312') if classroom_name else '',
75
                "__VIEWSTATE": self.payload['view_state'],
76
            }
77
            _request = self._post
78
        else:
79
            data = ""
80
            _request = self._get
81
82
        try:
83
            res = _request(self.schedule_url, data=data, **kwargs)
84
            if res.status_code != 200:
85
                raise RequestException
86
        except RequestException:
87
            raise ScheduleException(self.code, '获取教学场地课表失败')
88
        return res
89
90
    def _update_payload(self, *args, **kwargs):
91
        try:
92
            res = self._get_api(*args, **kwargs)
93
        except ScheduleException:
94
            return None
95
        self.payload = self._get_payload(res.text)
96
        return True
97
98
    @staticmethod
99
    def _get_payload(html):
100
        pre_soup = BeautifulSoup(html, "html.parser")
101
        view_state = pre_soup.find(attrs={"name": "__VIEWSTATE"})['value']
102
        searchbox = pre_soup.find("div", {"class": "searchbox"})
103
104
        schedule_year = searchbox.find("select", {"id": "xn"}).find(
105
            "option", {"selected": "selected"}).text
106
        schedule_term = searchbox.find("select", {"id": "xq"}).find(
107
            "option", {"selected": "selected"}).text
108
109
        campus = searchbox.find(id='ddlXq').find_all('option')
110
        type_list = searchbox.find(id='ddlJslb').find_all('option')
111
        name_list = searchbox.find(id='ddlJsmc').find_all('option')
112
        campus_list = [{"name": v.text, "value": v['value']} for v in campus]
113
        type_list = [{"name": v.text, "value": v['value']} for v in type_list]
114
        name_list = [{"name": v.text, "value": v['value']} for v in name_list]
115
        payload = {
116
            'view_state': view_state,
117
            'schedule_term': schedule_term,
118
            'schedule_year': schedule_year,
119
            'campus_list': campus_list,
120
            'classroom_type_list': type_list,
121
            'classroom_name_list': name_list,
122
        }
123
        return payload
124