Skip to content

Commit

Permalink
release v2.1.0 (190913)
Browse files Browse the repository at this point in the history
  • Loading branch information
zhongxinghong committed Sep 13, 2019
1 parent 738317f commit 34ad69b
Show file tree
Hide file tree
Showing 15 changed files with 655 additions and 594 deletions.
17 changes: 17 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,54 @@
Release History
===============

v2.1.0 (2019-09-13)
-------------------
- 修复了 Windows 下自定义参数不生效的问题


v2.0.9 (2019-09-12)
-------------------
- 对 v2.0.8 版本的完善,现在删除了与 `signal` 相关的逻辑,统一了两种运行模式下主进程退出的方式,确保了 `Ctrl + C` 的信号和子进程内部发出的终止信号均能使主进程正常退出


v2.0.8 (2019-09-11)
-------------------
- 对 v2.0.6 版本的完善,该版本在不带 `--with-monitor` 运行的情况下,也可以正确地接收到来自 `Ctrl + C` 的终止命令


v2.0.7 (2019-09-11)
-------------------
- 为 monitor 添加了与错误捕获记录相关的路由


v2.0.6 (2019-09-11)
-------------------
- 修复了在 Windows 下 `Ctrl + C` 无法退出程序的问题


v2.0.5 (2019-09-11)
-------------------
- 可以捕获 IAAA 登录时的密码错误和多次登录失败导致账号已被封禁的错误
- 完善了对多进程/线程下进程死亡的处理,以确保主进程在遇到错误时可以完全退出
- 现在 monitor 进程会在 loop 进程结束后自动退出


v2.0.4 (2019-09-10)
-------------------
- elective 客户端采用多会话机制


v2.0.3 (2019-09-09)
-------------------
- 可以捕获来自 IAAA 的错误
- 丰富了部分错误的提示信息


v2.0.2 (2019.09.09)
-------------------
- 添加了对处于选课计划第一页之后的课程的支持


v2.0.1 (2019.09.09)
-------------------
- 代码重构,删减大量冗余设计
Expand All @@ -45,18 +58,21 @@ v2.0.1 (2019.09.09)
- 可以捕获几个新遇到的系统异常/错误提示
- 美化了终端的输出格式


v1.0.4 (2019.02.22)
-------------------
- 修复了一处语法错误,位于 **main.py** 第 216-235 行的 `ignored.append`
- 纠正了一些变量名的拼写错误
- 可以捕获多选英语课引起的错误


v1.0.3 (2019.02.20)
-------------------
- 兼容了本科生辅双的登录界面,主修身份选课测试通过,辅双身份选课支持第一页
- 可以捕获共享回话引起的系统异常
- 可以捕获辅双登录无验证信息的系统异常


v1.0.2 (2019.02.19)
-------------------
- 研究生选课测试通过
Expand All @@ -67,6 +83,7 @@ v1.0.2 (2019.02.19)
- 更改单一 `User-Agent``User-Agent`
- 可以捕获课程互斥引起的错误提示


v1.0.1 (2019.02.18)
-------------------
- 上线版本,支持非辅双本科生选课
Expand Down
13 changes: 13 additions & 0 deletions MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
Migration Guide
====================

v2.0.9 -> 2.1.0
------------------

#### Development Related
- Windows 在创建多进程时只能采用 `spawn` 方法,子进程创建后并不直接共享父进程已经设置好的的用户配置项,因此还需要将用户配置项 `userInfo` 在进程中共享。但是 `userInfo` 直接影响着最基本的 `config.py` ,为了让用户自定义配置 `userInfo` 能够在子进程中被正确应用,`userInfo` 的更新至子线程 `_internal.py``config` 单例的第一次初始化必须早于任何依赖于 `config` 单例的方法的调用。
- 因此,这一版中对包调用的逻辑进行了大幅度的修改,删减了大部分包的在导入时即创建 `_config` 全局变量的逻辑,改成将 `config` 变量在函数使用时才创建,并且将 `loop.py``monitor.py` 中的所有全局变量和全局函数声明为局部
- 个人觉得这个改动很丑陋,但是由于我的开发经验有限,一时想不到其他的写法,如果你对这个问题有更好的解决方法,欢迎发 Issue !
- 个人的一个改进想法是把多进程全部换成多线程,这样就不需要考虑资源共享的问题


v2.0.6 -> v2.0.7
------------------
- monitor 进程中 `/loop` 路由细分为 `/main_loop``/login_loop` 两个路由
Expand All @@ -18,6 +28,7 @@ v2.0.4 -> v2.0.5

- 修改了错误类 `IAAANotSuccessError` 的全局错误码


v2.0.3 -> v2.0.4
------------------
- `config.ini` 内添加了 elective 多会话相关的配置
Expand All @@ -27,10 +38,12 @@ v2.0.3 -> v2.0.4

- 为了应对选课网偶发的会话过期问题,为 elective 客户端引入了多会话机制,并删除了旧有的定时重登机制。具体见 README 中的 [运行流程](/README.md#运行流程) 小节


v2.0.1 -> v2.0.2
------------------
- `config.ini` 内添加了 `client/supply_cancel_page` 值,以支持不处于选课计划第一页的课程


v1.0.4 -> v2.0.1
------------------
- 新版对 `config.ini` 内的绝大多数配置项名称做了修改,需要用新提供 `config.sample.ini` 重新填写一遍配置
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# PKUAutoElective

北大选课网 **补退选** 阶段自动选课小工具 v2.0.9 (2019.09.12)
北大选课网 **补退选** 阶段自动选课小工具 v2.1.0 (2019.09.13)

目前支持 `本科生(含辅双)``研究生` 选课

Expand Down
4 changes: 2 additions & 2 deletions autoelective/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
# filename: __init__.py
# modified: 2019-09-11

__version__ = "2.0.9"
__date__ = "2019.09.12"
__version__ = "2.1.0"
__date__ = "2019.09.13"
__author__ = "Rabbit"
11 changes: 10 additions & 1 deletion autoelective/_internal.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,18 @@
# filename: _internal.py
# modified: 2019-09-08

__all__ = ["mkdir","abspath"]
__all__ = [

"mkdir",
"abspath"

"userInfo",
]

import os

userInfo = {} # shared the user's custom options


def mkdir(path):
if not os.path.exists(path):
Expand All @@ -15,3 +23,4 @@ def mkdir(path):
def abspath(*paths):
_BASE_DIR = os.path.dirname(__file__)
return os.path.normpath(os.path.abspath(os.path.join(_BASE_DIR, *paths)))

8 changes: 4 additions & 4 deletions autoelective/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@
from requests.models import Request
from requests.sessions import Session
from requests.cookies import extract_cookies_to_jar
from .const import DEFAULT_CONFIG_INI


class BaseClient(object):

TIMEOUT = 10
HEADERS = {}
PROXIES = {}

def __init__(self, *args, **kwargs):
if self.__class__ is __class__:
raise NotImplementedError

self._timeout = kwargs.get("timeout", DEFAULT_CONFIG_INI)

self._session = Session()
self._session.headers.update(self.__class__.HEADERS)
self._session.proxies = self.__class__.PROXIES


def _request(self, method, url,
Expand Down Expand Up @@ -57,7 +57,7 @@ def _request(self, method, url,

# Send the request.
send_kwargs = {
'timeout': timeout or self.__class__.TIMEOUT, # set default timeout
'timeout': timeout or self._timeout, # set default timeout
'allow_redirects': allow_redirects,
}
send_kwargs.update(settings)
Expand Down
23 changes: 11 additions & 12 deletions autoelective/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,19 @@
import os
from configparser import RawConfigParser
from .utils import Singleton
from .const import CONFIG_INI
from .const import DEFAULT_CONFIG_INI
from ._internal import userInfo


class BaseConfig(object, metaclass=Singleton):
class BaseConfig(object):

CONFIG_FILE = ""
ALLOW_NO_VALUE = True

def __init__(self):
def __init__(self, config_file=None, allow_no_value=True):
if self.__class__ is __class__:
raise NotImplementedError
file = os.path.normpath(os.path.abspath(self.__class__.CONFIG_FILE))
file = os.path.normpath(os.path.abspath(config_file))
if not os.path.exists(file):
raise FileNotFoundError("config file was not found: %s" % file)
self._config = RawConfigParser(allow_no_value=self.__class__.ALLOW_NO_VALUE)
self._config = RawConfigParser(allow_no_value=allow_no_value)
self._config.read(file, encoding="utf-8-sig") # 必须显示指明 encoding

def get(self, section, key):
Expand All @@ -38,17 +36,18 @@ def getboolean(self, section, key):
return self._config.getboolean(section, key)


class AutoElectiveConfig(BaseConfig):

CONFIG_FILE = CONFIG_INI
class AutoElectiveConfig(BaseConfig, metaclass=Singleton):

def __init__(self):
config_file = userInfo.get("CONFIG_INI", DEFAULT_CONFIG_INI)
allow_no_value = True
super().__init__(config_file, allow_no_value)

# MAKR: value constraints

ALLOWED_IDENTIFY = ("bzx","bfx")
ALLOWED_CSV_CODING = ("utf-8","gbk")


# MAKR: model

# [coding]
Expand Down
30 changes: 17 additions & 13 deletions autoelective/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
"CAPTCHA_CACHE_DIR",
"REQUEST_LOG_DIR",

"COURSE_UTF8_CSV",
"COURSE_GBK_CSV",
"CONFIG_INI",
"DEFAULT_COURSE_UTF8_CSV",
"DEFAULT_COURSE_GBK_CSV",
"DEFAULT_CONFIG_INI",

"USER_AGENT",
"DEFAULT_CLIENT_TIMEOUT",

"IAAALinks",
"ElectiveLinks",
Expand All @@ -35,17 +36,17 @@
SIGNAL_KILL_ALL_THREADS = 2


BASE_DIR = abspath("./")
MODEL_DIR = abspath("./captcha/model/")
CACHE_DIR = abspath("../cache/")
CAPTCHA_CACHE_DIR = abspath("../cache/captcha/")
LOG_DIR = abspath("../log/")
ERROR_LOG_DIR = abspath("../log/error")
REQUEST_LOG_DIR = abspath("../log/request/")
BASE_DIR = abspath("./")
MODEL_DIR = abspath("./captcha/model/")
CACHE_DIR = abspath("../cache/")
CAPTCHA_CACHE_DIR = abspath("../cache/captcha/")
LOG_DIR = abspath("../log/")
ERROR_LOG_DIR = abspath("../log/error")
REQUEST_LOG_DIR = abspath("../log/request/")

COURSE_UTF8_CSV = abspath("../course.utf-8.csv")
COURSE_GBK_CSV = abspath("../course.gbk.csv")
CONFIG_INI = abspath("../config.ini")
DEFAULT_COURSE_UTF8_CSV = abspath("../course.utf-8.csv")
DEFAULT_COURSE_GBK_CSV = abspath("../course.gbk.csv")
DEFAULT_CONFIG_INI = abspath("../config.ini")


mkdir(CACHE_DIR)
Expand Down Expand Up @@ -80,6 +81,9 @@
])
# USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/75.0.3770.90 Chrome/75.0.3770.90 Safari/537.36"

DEFAULT_CLIENT_TIMEOUT = 10


class IAAALinks(object):
"""
Host
Expand Down
14 changes: 3 additions & 11 deletions autoelective/elective.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,7 @@
import random
from .client import BaseClient
from .hook import *
from .config import AutoElectiveConfig
from .logger import ConsoleLogger
from .const import USER_AGENT, ElectiveLinks


_logger = ConsoleLogger("elective")
_config = AutoElectiveConfig()
from .const import USER_AGENT, DEFAULT_CLIENT_TIMEOUT, ElectiveLinks


_hooks_check_status_code = get_hooks(
Expand Down Expand Up @@ -57,10 +51,8 @@ class ElectiveClient(BaseClient):
"User-Agent": USER_AGENT,
}

TIMEOUT = _config.electiveClientTimeout # elective 拥挤时可能会出现网络堵塞,可能需要将时间设长

def __init__(self, id):
super(ElectiveClient, self).__init__()
def __init__(self, id, **kwargs):
super().__init__(**kwargs)
self._id = id

@property
Expand Down
14 changes: 3 additions & 11 deletions autoelective/iaaa.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,9 @@

from .client import BaseClient
from .hook import *
from .logger import ConsoleLogger
from .config import AutoElectiveConfig
from .const import USER_AGENT, IAAALinks, ElectiveLinks


_config = AutoElectiveConfig()
_logger = ConsoleLogger("iaaa")

_hooks_check_iaaa_success = get_hooks(
debug_print_request,
check_status_code,
Expand All @@ -31,10 +26,7 @@ class IAAAClient(BaseClient):
"X-Requested-With": "XMLHttpRequest",
}

TIMEOUT = _config.iaaaClientTimeout


def oauth_login(self, **kwargs):
def oauth_login(self, username, password, **kwargs):
headers = kwargs.pop("headers", {})
headers["Referer"] = IAAALinks.OauthHomePage + \
"?appID=syllabus" + \
Expand All @@ -44,8 +36,8 @@ def oauth_login(self, **kwargs):
url=IAAALinks.OauthLogin,
data={
"appid": "syllabus",
"userName": _config.iaaaID,
"password": _config.iaaaPassword,
"userName": username,
"password": password,
"randCode": "",
"smsCode": "",
"otpCode": "",
Expand Down
Loading

0 comments on commit 34ad69b

Please sign in to comment.