diff --git a/CHANGELOG b/CHANGELOG index 17b98d9..3127b64 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +v0.3.0 2019-05-27 +1. 教务系统改版修复 +2. 增加油猴脚本 + v0.2.1 2019-04-02 1. 添加未开放选课处理 2. cookie打印修复 diff --git a/Protocol analysis v2.md b/Protocol analysis v2.md index ea8f643..2a03749 100644 --- a/Protocol analysis v2.md +++ b/Protocol analysis v2.md @@ -80,7 +80,7 @@ POST参数:\ #### 选课接口 地址:`http://i.sjtu.edu.cn/xsxk/zzxkyzb_xkBcZyZzxkYzb.html?gnmkdm=N253512&su=xxx`\ 必须参数(经过测试可以省略的就不写了): -- `jxb_ids`:唯一班号,教学班最后一列的6位数字 +- `jxb_ids`:32位课号ID - `xkkz_id`:未知ID,和选课轮数有关,同一轮,同一课程类型为定值。 - `njdm_id`:年级ID?推测为届数。 - `zyh_id`:未知ID。 diff --git a/README.md b/README.md index 9a05f70..911bf37 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # sjtu-automata -![Version](https://img.shields.io/badge/Version-0.2.1-blue.svg) ![Language](https://img.shields.io/badge/Language-Python3-red.svg) ![License](https://img.shields.io/badge/License-GPL--3.0-yellow.svg) +![Version](https://img.shields.io/badge/Version-0.3.0-blue.svg) ![Language](https://img.shields.io/badge/Language-Python3-red.svg) ![License](https://img.shields.io/badge/License-GPL--3.0-yellow.svg) **注意!此版本为BETA版,未经过严格测试,可能存在BUG,如有问题请提交[issue](https://github.com/MXWXZ/AutoElect/issues)** @@ -39,11 +39,17 @@ Ubuntu 18.04: 其他版本/发行版/Windows等自行看文档:https://github.com/tesseract-ocr/tesseract/wiki ## 简单使用说明 -1. 查看课号:想选的课“教学班”一栏最后6位数字即为唯一课号 -2. 查看课程类型:主修课为0,通识课为1,通选课为2(仅适用于只有这三种课的情况,更多需要请提交issue) -3. 使用命令选课,例如选择主修课,课号123456,通识课,课号234567,不使用ocr: +- 由于选课系统再次更新,需要传递的参数改变,因此建议使用油猴脚本获取ID:https://www.tampermonkey.net/ +- 插件安装完成后点击这里进入脚本安装页面:https://github.com/MXWXZ/sjtu-automata/raw/master/sjtu-automata.user.js +- 下面的教程以安装插件之后为准,如果不安装油猴脚本也可以自行查看网页源码提取相关ID - autoelect 0 123456 1 234567 +1. 查看课号:想选的课“教学班”第二行的32位字符串即为唯一课号 +2. 查看课程类型:标签页第二行的32位字符串即为课程类型 +3. 使用命令选课,格式为`autoelect [32位课程类型ID] [32位课号ID]`: + + autoelect ABCDEFGHIJKLMNOPQRSTUVWXYZ123456 BCDEFGHIJKLMNOPQRSTUVWXYZ1234567 CDEFGHIJKLMNOPQRSTUVWXYZ12345678 DEFGHIJKLMNOPQRSTUVWXYZ123456789 + + 上述命令将会选`ABCDEFGHIJKLMNOPQRSTUVWXYZ123456`课程类型下的`BCDEFGHIJKLMNOPQRSTUVWXYZ1234567`课和`CDEFGHIJKLMNOPQRSTUVWXYZ12345678`课程类型下的`DEFGHIJKLMNOPQRSTUVWXYZ123456789`课,如果需要更多可以在后面继续添加。 注:程序运行过程中输入`s`可以查看选课状态 @@ -69,5 +75,5 @@ Ubuntu 18.04: | -h | --help | 显示帮助 | - `CLASSTYPE`和`CLASSID`成对出现,可以出现多对同步进行,但至少有一对 -- `CLASSTYPE`:主修课为0,通识课为1,通选课为2(仅适用于只有这三种课的情况,更多需要请提交issue) -- `CLASSID`:“教学班”一栏最后6位数字 +- `CLASSTYPE`:32位课程类型ID +- `CLASSID`:32位课号ID diff --git a/sjtu-automata.user.js b/sjtu-automata.user.js new file mode 100644 index 0000000..7c62570 --- /dev/null +++ b/sjtu-automata.user.js @@ -0,0 +1,79 @@ +// ==UserScript== +// @name sjtu-automata +// @namespace http://tampermonkey.net/ +// @version 1.0 +// @description show classid under classname. +// @author MXWXZ +// @match *://i.sjtu.edu.cn/xsxk/zzxkyzb_cxZzxkYzbIndex.html* +// @homepageURL https://github.com/MXWXZ/sjtu-automata/ +// @supportURL https://github.com/MXWXZ/sjtu-automata/issues/ +// @downloadURL https://raw.githubusercontent.com/MXWXZ/sjtu-automata/master/sjtu-automata.user.js +// @updateURL https://raw.githubusercontent.com/MXWXZ/sjtu-automata/master/sjtu-automata.user.js +// @grant none +// ==/UserScript== + +function waitForKeyElements(selectorTxt, actionFunction, bWaitOnce, iframeSelector) { + var targetNodes, btargetsFound; + if (typeof iframeSelector == "undefined") + targetNodes = jQuery(selectorTxt); + else + targetNodes = jQuery(iframeSelector).contents() + .find(selectorTxt); + + if (targetNodes && targetNodes.length > 0) { + btargetsFound = true; + targetNodes.each(function () { + var jThis = jQuery(this); + var alreadyFound = jThis.data('alreadyFound') || false; + + if (!alreadyFound) { + var cancelFound = actionFunction(jThis); + if (cancelFound) + btargetsFound = false; + else + jThis.data('alreadyFound', true); + } + }); + } + else { + btargetsFound = false; + } + + var controlObj = waitForKeyElements.controlObj || {}; + var controlKey = selectorTxt.replace(/[^\w]/g, "_"); + var timeControl = controlObj[controlKey]; + + if (btargetsFound && bWaitOnce && timeControl) { + clearInterval(timeControl); + delete controlObj[controlKey] + } + else { + if (!timeControl) { + timeControl = setInterval(function () { + waitForKeyElements(selectorTxt, + actionFunction, + bWaitOnce, + iframeSelector + ); + }, 300); + controlObj[controlKey] = timeControl; + } + } + waitForKeyElements.controlObj = controlObj; +} + +function showid(node){ + let id=node.children().children()[0].innerHTML; + node.children('.jxbmc').append('

'+id+'

'); +} + +(function() { + 'use strict'; + + let node=$('.nav.nav-tabs.sl_nav_tabs li'); + node.each(function(){ + let str=$(this).children('a')[0].getAttribute("onclick"); + $(this).append('

'+str.substr(str.indexOf("','")+3,32)+'  

'); + }); + waitForKeyElements('.body_tr', showid, false); +})(); \ No newline at end of file diff --git a/sjtu_automata/__version__.py b/sjtu_automata/__version__.py index 9051f97..413d4a9 100644 --- a/sjtu_automata/__version__.py +++ b/sjtu_automata/__version__.py @@ -2,7 +2,7 @@ __description__ = 'Auto elect script for SJTUer.' __url__ = 'https://github.com/MXWXZ/sjtu-automata' __update_url__ = 'https://raw.githubusercontent.com/MXWXZ/sjtu-automata/master/version' -__version__ = '0.2.1' +__version__ = '0.3.0' __author__ = 'MXWXZ' __author_email__ = 'me@imwxz.com' __license__ = 'GNU General Public License v3 (GPLv3)' diff --git a/sjtu_automata/autoelect.py b/sjtu_automata/autoelect.py index 73a040b..e24b73a 100644 --- a/sjtu_automata/autoelect.py +++ b/sjtu_automata/autoelect.py @@ -1,8 +1,3 @@ -from sjtu_automata.electsys.automata import ( - get_studentid, get_params, elect_class) -from sjtu_automata.credential import login -from sjtu_automata.__version__ import __author__, __url__, __version__ -from sjtu_automata import check_update, echoerror, echoinfo, echowarning import getopt import sys from time import sleep @@ -12,7 +7,11 @@ import threading sys.path.append('../') - +from sjtu_automata.electsys.automata import ( + get_studentid, get_params, elect_class) +from sjtu_automata.credential import login +from sjtu_automata.__version__ import __author__, __url__, __version__ +from sjtu_automata import check_update, echoerror, echoinfo, echowarning class UserInterface(object): def __init__(self): @@ -53,7 +52,7 @@ def login(self, ocr, delay): while 1: self.params = get_params(self.session, self.studentid) - if self.params['xkkz_id'][0] and self.params['xkkz_id'][1] and self.params['xkkz_id'][2] and self.params['njdm_id'] and self.params['zyh_id']: + if self.params['njdm_id'] and self.params['zyh_id']: break echoinfo('Not open, retry in %d seconds...' % delay) sleep(delay) @@ -61,10 +60,10 @@ def login(self, ocr, delay): echoinfo('Login successful!') return True - def __elect_thread(self, tid, classtype, classid, delay): + def __elect_thread(self, tid, xkkzid, classid, delay): while self.status[tid] == 2 or self.status[tid] == 4 or self.status[tid] == -1: ret = elect_class(self.session, self.studentid, - self.params, classtype, classid) + self.params, xkkzid, classid) with self.tl[tid]: if self.status[tid] != 0 and self.status[tid] != 1 and self.status[tid] != 3: self.status[tid] = ret @@ -73,10 +72,10 @@ def __elect_thread(self, tid, classtype, classid, delay): break sleep(delay) - def add_elect(self, number, classtype, classid, delay): + def add_elect(self, number, xkkzid, classid, delay): for i in range(number): self.tp.append(threading.Thread( - target=self.__elect_thread, args=(self.id, classtype, classid, delay,))) + target=self.__elect_thread, args=(self.id, xkkzid, classid, delay,))) self.tl.append(threading.Lock()) self.tclass.append(classid) self.status.append(-1) @@ -170,14 +169,15 @@ def cli(no_update, ocr, print_cookie, delay, check_delay, number, classtypeid): exit() ui = UserInterface() - ui.login(ocr, check_delay) + if not ui.login(ocr, check_delay): + exit() if print_cookie: ui.print_cookie() for i in range(0, len(classtypeid), 2): - if not (0 <= int(classtypeid[i]) <= 2): + if len(classtypeid[i]) != 32: echowarning('Class type ' + classtypeid[i] + ' invalid! Ignore.') continue - ui.add_elect(number, int(classtypeid[i]), classtypeid[i+1], delay) + ui.add_elect(number, classtypeid[i], classtypeid[i+1], delay) ui.start_elect() cmd = threading.Thread(target=ui.get_input) cmd.daemon = True diff --git a/sjtu_automata/electsys/automata.py b/sjtu_automata/electsys/automata.py index 8f9c11d..75ef940 100644 --- a/sjtu_automata/electsys/automata.py +++ b/sjtu_automata/electsys/automata.py @@ -62,26 +62,18 @@ def get_params(session, studentid): Returns: dict: - xkkz_id: list, [0] is '主修课程', [1] is '通识课', [2] is '通选课' njdm_id: str, njdm_id zyh_id: str, zyh_id """ params = {'gnmkdm': 'N253512', 'layout': 'default', 'su': studentid} req = _request( session, 'GET', 'http://i.sjtu.edu.cn/xsxk/zzxkyzb_cxZzxkYzbIndex.html', params=params) - xkkz_id = [] - xkkz_id.append(re_search( - r'\'01\',\'(.*)\'\)" role="tab" data-toggle="tab">', req)) - xkkz_id.append(re_search( - r'\'10\',\'(.*)\'\)" role="tab" data-toggle="tab">', req)) - xkkz_id.append(re_search( - r'\'11\',\'(.*)\'\)" role="tab" data-toggle="tab">', req)) njdm_id = re_search(r'id="njdm_id" value="(.*?)"/>', req) zyh_id = re_search(r'id="zyh_id" value="(.*?)"/>', req) - return {'xkkz_id': xkkz_id, 'njdm_id': njdm_id, 'zyh_id': zyh_id} + return {'njdm_id': njdm_id, 'zyh_id': zyh_id} -def elect_class(session, studentid, params, classtype, classid): +def elect_class(session, studentid, params, xkkzid, classid): """Elect class. Directly elect class. @@ -91,16 +83,14 @@ def elect_class(session, studentid, params, classtype, classid): session: requests session, login session. studentid: str, student id. params: dict, get_params returned - classtype: int, 0 is '主修课程', 1 is '通识课', 2 is '通选课' + xkkzid: str, 32 length id classid: str, class id Returns: int, -1 for param error, 0 for success, 1 for time conflict, 2 for full, 3 for param error, 4 for other. """ - if not (0 <= classtype <= 2): - return -1 post_params = {'gnmkdm': 'N253512', 'su': studentid} - data = {'jxb_ids': classid, 'xkkz_id': params['xkkz_id'][classtype], + data = {'jxb_ids': classid, 'xkkz_id': xkkzid, 'njdm_id': params['njdm_id'], 'zyh_id': params['zyh_id']} req = _request( diff --git a/version b/version index 7dff5b8..9325c3c 100644 --- a/version +++ b/version @@ -1 +1 @@ -0.2.1 \ No newline at end of file +0.3.0 \ No newline at end of file