From 976b2fd54b81cda4214610936eeb026953d01efe Mon Sep 17 00:00:00 2001 From: lensferno Date: Mon, 21 Nov 2022 21:12:14 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=BB=E8=A6=81=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=EF=BC=9A=E7=A0=94=E7=A9=B6=E7=94=9F=EF=BC=9A=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E3=80=81=E5=AD=A6=E7=94=9F=E4=BF=A1=E6=81=AF=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E3=80=81=E8=AF=BE=E8=A1=A8=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/linghang/mywust/core/api/Graduate.java | 9 ++ .../mywust/core/exception/ApiException.java | 38 ++++++ .../physics/PhysicsCoursePageParser.java | 2 +- .../GraduateCourseTablePageParser.java | 121 ++++++++++++++++++ .../GraduateStudentInfoPageParser.java | 97 ++++++++++++++ .../parser/undergraduate/ExamInfoParser.java | 2 +- .../undergraduate/StudentInfoPageParser.java | 2 +- .../graduate/GraduateRequestFactory.java | 46 +++++++ .../undergrade/BkjxRequestFactory.java | 8 +- .../CourseTableRequestParamFactory.java | 46 +++---- .../service/undergraduate/ExamInfoApi.java | 3 +- .../service/undergraduate/StudentInfoApi.java | 3 +- .../mywust/captcha/SolvedImageCaptcha.java | 25 ++++ .../mywust/captcha/UnsolvedImageCaptcha.java | 19 +++ .../mywust/captcha/solver/CaptchaSolver.java | 8 ++ .../LinghangOcrServiceCaptchaSolver.java | 11 ++ .../solver/LocalPaddleOcrCaptchaSolver.java | 11 ++ .../linghang/mywust/model/global/Course.java | 14 +- .../{undergrade => global}/ExamInfo.java | 2 +- .../{undergrade => global}/StudentInfo.java | 2 +- .../network/entitys/FormBodyBuilder.java | 4 +- .../src/test/java/CourseTableTest.java | 2 - mywust-test/src/test/java/ExamInfoTest.java | 2 +- .../src/test/java/StudentInfoPageTest.java | 5 +- pom.xml | 9 ++ 25 files changed, 445 insertions(+), 46 deletions(-) create mode 100644 mywust-core/src/main/java/cn/linghang/mywust/core/api/Graduate.java create mode 100644 mywust-core/src/main/java/cn/linghang/mywust/core/exception/ApiException.java create mode 100644 mywust-core/src/main/java/cn/linghang/mywust/core/parser/postgraduate/GraduateCourseTablePageParser.java create mode 100644 mywust-core/src/main/java/cn/linghang/mywust/core/parser/postgraduate/GraduateStudentInfoPageParser.java create mode 100644 mywust-core/src/main/java/cn/linghang/mywust/core/request/graduate/GraduateRequestFactory.java create mode 100644 mywust-model/src/main/java/cn/linghang/mywust/captcha/SolvedImageCaptcha.java create mode 100644 mywust-model/src/main/java/cn/linghang/mywust/captcha/UnsolvedImageCaptcha.java create mode 100644 mywust-model/src/main/java/cn/linghang/mywust/captcha/solver/CaptchaSolver.java create mode 100644 mywust-model/src/main/java/cn/linghang/mywust/captcha/solver/LinghangOcrServiceCaptchaSolver.java create mode 100644 mywust-model/src/main/java/cn/linghang/mywust/captcha/solver/LocalPaddleOcrCaptchaSolver.java rename mywust-model/src/main/java/cn/linghang/mywust/model/{undergrade => global}/ExamInfo.java (97%) rename mywust-model/src/main/java/cn/linghang/mywust/model/{undergrade => global}/StudentInfo.java (91%) diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/api/Graduate.java b/mywust-core/src/main/java/cn/linghang/mywust/core/api/Graduate.java new file mode 100644 index 0000000..72d1c8d --- /dev/null +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/api/Graduate.java @@ -0,0 +1,9 @@ +package cn.linghang.mywust.core.api; + +public class Graduate { + public static final String GRADUATE_CAPTCHA_API = "http://59.68.177.189/pyxx/PageTemplate/NsoftPage/yzm/createyzm.aspx"; + public static final String GRADUATE_LOGIN_API = "http://59.68.177.189/pyxx/login.aspx"; + + public static final String GRADUATE_STUDENT_INFO_API = "http://59.68.177.189/pyxx/grgl/student_info1.aspx"; + public static final String GRADUATE_COURSE_TABLE_API = "http://59.68.177.189/pyxx/pygl/kbcx_xs.aspx"; +} diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/exception/ApiException.java b/mywust-core/src/main/java/cn/linghang/mywust/core/exception/ApiException.java new file mode 100644 index 0000000..5fdc692 --- /dev/null +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/exception/ApiException.java @@ -0,0 +1,38 @@ +package cn.linghang.mywust.core.exception; + +public class ApiException extends BasicException { + private final int code; + + public ApiException(int code) { + this.code = code; + } + + public ApiException(int code, String message) { + super(message); + this.code = code; + } + + public int getCode() { + return code; + } + + @Override + public String toString() { + return "接口调用异常: " + code; + } + + public static class ApiExceptionCode { + // 统一认证的异常 + public static final int UNI_LOGIN_PASSWORD_WRONG = 100101; + public static final int UNI_LOGIN_USER_NOT_EXISTS = 100102; + public static final int UNI_LOGIN_USER_BANNED = 100103; + + // 共有异常码:cookie无效 + // 放一起了 + public static final int BKJX_COOKIE_INVALID = 110101; + public static final int LIBRARY_COOKIE_INVALID = 12101; + public static final int PHYSICS_COOKIE_INVALID = 130101; + public static final int GRADE_COOKIE_INVALID = 140101; + } + +} \ No newline at end of file diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/parser/physics/PhysicsCoursePageParser.java b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/physics/PhysicsCoursePageParser.java index 23b24bc..c18b16a 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/parser/physics/PhysicsCoursePageParser.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/physics/PhysicsCoursePageParser.java @@ -63,7 +63,7 @@ public class PhysicsCoursePageParser implements Parser> { Matcher weekDayMatcher = PHYSICS_COURSE_WEEKDAY_PATTERN.matcher(time); if (weekDayMatcher.find()) { - course.setWeekDay(Course.WEEKDAY_MAP.getOrDefault(weekDayMatcher.group("weekDay"), 1)); + course.setWeekDay(weekDayMatcher.group("weekDay")); } Matcher startEndMatcher = PHYSICS_COURSE_START_END_PATTERN.matcher(time); diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/parser/postgraduate/GraduateCourseTablePageParser.java b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/postgraduate/GraduateCourseTablePageParser.java new file mode 100644 index 0000000..c70197b --- /dev/null +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/postgraduate/GraduateCourseTablePageParser.java @@ -0,0 +1,121 @@ +package cn.linghang.mywust.core.parser.postgraduate; + +import cn.linghang.mywust.core.exception.ParseException; +import cn.linghang.mywust.core.parser.Parser; +import cn.linghang.mywust.model.global.ClassRoom; +import cn.linghang.mywust.model.global.Course; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class GraduateCourseTablePageParser implements Parser> { + + private static final Pattern COURSE_TABLE_REGEX = Pattern.compile("课程:(?.*?)
班级:(?.*?)
\\((?.*?)\\)
(?.*?)
(?
.*?)
主讲教师:(?.*?)
"); + + private static final Pattern WEEK_REGEX = Pattern.compile("(?\\d+)-(?\\d+)周.*?星期(?[一二三四五六七日天])"); + + @Override + public List parse(String html) throws ParseException { + Document document = Jsoup.parse(html); + Element table = document.getElementById("DataGrid1"); + if (table == null) { + throw new ParseException("解析研究生课表失败:关键元素不存在...", html); + } + + // 初步拿到所有的课程格子 + Elements girds = table.getElementsByAttribute("rowspan"); + String girdsHtml = girds.outerHtml(); + + List courses = new ArrayList<>(girds.size()); + Course.CourseBuilder courseBuilder = Course.builder(); + + // 正则提取每一段课程文本 + Matcher matcher = COURSE_TABLE_REGEX.matcher(girdsHtml); + while (matcher.find()) { + String name = matcher.group("name"); + courseBuilder.name(name); + + String teachClass = matcher.group("class"); + courseBuilder.teachClass(teachClass); + + String classroom = matcher.group("classRoom"); + courseBuilder.classroom(new ClassRoom("", "", "", classroom)); + + String teacher = matcher.group("teacher"); + courseBuilder.teacher(teacher); + + String weekStr = matcher.group("week"); + this.parseWeek(weekStr, courseBuilder); + + String section = matcher.group("section"); + this.fillCourseList(section, courseBuilder, courses); + } + + return courses; + } + + /** + * 解析周次信息文本 + * + * @param weekText 周次文本,如“3-14周:连续周 星期三” + * @param builder Lesson的builder + */ + private void parseWeek(String weekText, Course.CourseBuilder builder) { + Matcher matcher = WEEK_REGEX.matcher(weekText); + if (matcher.find()) { + String startWeek = matcher.group("startWeek"); + String endWeek = matcher.group("endWeek"); + String weekDay = matcher.group("weekDay"); + + builder.startWeek(Integer.parseInt(startWeek)); + builder.endWeek(Integer.parseInt(endWeek)); + builder.weekDay(Course.getWeekDayNumber(weekDay)); + } + } + + /** + * 解析节次,并将解析出来的完整的节次放入List中 + * + * @param sectionText 提取出来的节次文本,如“上1,上2,上3,上4,下1,下2” + * @param builder LessonImpl中的builder + * @param courses 存放Lesson的List + */ + private void fillCourseList(String sectionText, Course.CourseBuilder builder, List courses) { + String[] sections = sectionText.split(","); + for (int i = 0; i < sections.length / 2; i += 2) { + int startSection = this.getSection(sections[i]); + int endSection = this.getSection(sections[i + 1]); + + builder.startSection(startSection); + builder.endSection(endSection); + + courses.add(builder.build()); + } + } + + /** + * 将上1,下2,晚1这种相对的节次格式转换为相应的绝对节次 + * + * @param time 类似于上1,下2,晚1这种相对的节次格式文本 + * @return 相应的绝对节次 + */ + private int getSection(String time) { + int i = time.charAt(1) - 48; + switch (time.charAt(0)) { + case '上': + return i; + case '下': + return i + 4; + case '晚': + return i + 8; + default: + return 1; + } + } +} diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/parser/postgraduate/GraduateStudentInfoPageParser.java b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/postgraduate/GraduateStudentInfoPageParser.java new file mode 100644 index 0000000..36cbbdf --- /dev/null +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/postgraduate/GraduateStudentInfoPageParser.java @@ -0,0 +1,97 @@ +package cn.linghang.mywust.core.parser.postgraduate; + +import cn.linghang.mywust.core.exception.ParseException; +import cn.linghang.mywust.core.parser.Parser; +import cn.linghang.mywust.model.global.StudentInfo; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Element; + +public class GraduateStudentInfoPageParser implements Parser { + + private static final String INFO_TABLE_XPATH = "//*[@id=\"Form1\"]/table/tbody/tr[2]/td/table/tbody/tr[2]/td/table"; + + @Override + public StudentInfo parse(String html) throws ParseException { + Element table = Jsoup.parse(html).selectXpath(INFO_TABLE_XPATH).get(0); + + StudentInfo student = new StudentInfo(); + + Element studentNumberElement = table.getElementById("txtxh"); + student.setStudentNumber(this.getAttr(studentNumberElement, "value")); + +// Element gradeElement = table.getElementById("txtnj"); +// int grade = Integer.parseInt(this.getAttr(gradeElement, "value")); + + Element idNumberElement = table.getElementById("txtsfzh"); + student.setIdNumber(this.getAttr(idNumberElement, "value")); + + Element nationalityElement = table.getElementById("drpmz"); + student.setNationality(this.getSelectContent(nationalityElement)); + + Element hometownElement = table.getElementById("txtjg"); + student.setHometown(this.getAttr(hometownElement, "value")); + + Element nameElement = table.getElementById("txtxm"); + student.setName(this.getAttr(nameElement, "value")); + + Element birthdayElement = table.getElementById("lblcsrq"); + student.setBirthday(this.getText(birthdayElement)); + + Element collegeElement = table.getElementById("droyx"); + student.setCollege(this.getSelectContent(collegeElement)); + + Element majorElement = table.getElementById("drozy"); + student.setMajor(this.getSelectContent(majorElement)); + + Element genderElement = table.getElementById("droxb"); + + student.setSex(this.getSelectContent(genderElement)); + + // 研究生没有班级 + student.setClazz(""); + + return student; + } + + /** + * 从Element中拿到指定的标签值 + * @param element 元素对象 + * @param key 标签值的key + * @return 相应的值,若element为空则返回空字符串 + */ + private String getAttr(Element element, String key) { + if (element == null) { + return ""; + } else { + return element.attr(key); + } + } + + /** + * 从Element中拿到指定的文本内容 + * @param element 元素对象 + * @return 相应的值,若element为空则返回空字符串 + */ + public String getText(Element element) { + if (element == null) { + return ""; + } else { + return element.ownText(); + } + } + + /** + * 从select类型的Element中拿取到已选中的选项值 + * @param element 元素对象 + * @return 相应的值,若element为空则返回空字符串 + */ + public String getSelectContent(Element element) { + if (element == null) { + return ""; + } else { + return element.getElementsByAttributeValue("selected", "selected") + .get(0) + .ownText(); + } + } +} diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/ExamInfoParser.java b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/ExamInfoParser.java index 8a3828a..8a5e013 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/ExamInfoParser.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/ExamInfoParser.java @@ -3,7 +3,7 @@ package cn.linghang.mywust.core.parser.undergraduate; import cn.linghang.mywust.core.exception.ParseException; import cn.linghang.mywust.core.parser.Parser; import cn.linghang.mywust.core.parser.undergraduate.xpath.ExamInfoXpath; -import cn.linghang.mywust.model.undergrade.ExamInfo; +import cn.linghang.mywust.model.global.ExamInfo; import org.jsoup.Jsoup; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/StudentInfoPageParser.java b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/StudentInfoPageParser.java index 4da6c40..a6196eb 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/StudentInfoPageParser.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/StudentInfoPageParser.java @@ -3,7 +3,7 @@ package cn.linghang.mywust.core.parser.undergraduate; import cn.linghang.mywust.core.exception.ParseException; import cn.linghang.mywust.core.parser.Parser; import cn.linghang.mywust.core.parser.undergraduate.xpath.StudentInfoXpath; -import cn.linghang.mywust.model.undergrade.StudentInfo; +import cn.linghang.mywust.model.global.StudentInfo; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/request/graduate/GraduateRequestFactory.java b/mywust-core/src/main/java/cn/linghang/mywust/core/request/graduate/GraduateRequestFactory.java new file mode 100644 index 0000000..74bfbde --- /dev/null +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/request/graduate/GraduateRequestFactory.java @@ -0,0 +1,46 @@ +package cn.linghang.mywust.core.request.graduate; + +import cn.linghang.mywust.captcha.SolvedImageCaptcha; +import cn.linghang.mywust.core.api.Graduate; +import cn.linghang.mywust.core.request.RequestFactory; +import cn.linghang.mywust.network.entitys.HttpRequest; +import cn.linghang.mywust.util.StringUtil; + +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +public class GraduateRequestFactory extends RequestFactory { + public static HttpRequest captchaRequest() { + return makeHttpRequest(Graduate.GRADUATE_CAPTCHA_API); + } + + private static final Map CONST_PARAMS = new HashMap<>(5); + static { + CONST_PARAMS.put("__VIEWSTATE", "/wEPDwUENTM4MWQYAQUeX19Db250cm9sc1JlcXVpcmVQb3N0QmFja0tleV9fFgIFEl9jdGwwOkltYWdlQnV0dG9uMQUSX2N0bDA6SW1hZ2VCdXR0b24yXnZLY54iSWFQ6B2yKH0EisNqU3/eKWEJPibQUElowzU="); + CONST_PARAMS.put("__EVENTVALIDATION", "/wEdAAYVkBquZFuFxLpraDgB64v+UDagjadrq+xukJizXKfuf485DjYUnSc4B1y8D5WGXeCaN+cQ7B52HzGj0ueO5HRlbdfASR9MjKgO1uRUmJC5kWf476Bpzok4CsBoBh+4Dc7vLkoP0tXUghu7H8qg++pYHeGok+i2xPFtG5oj0qB2dw=="); + CONST_PARAMS.put("__VIEWSTATEGENERATOR", "496CE0B8"); + CONST_PARAMS.put("_ctl0:ImageButton1.x", "39"); + CONST_PARAMS.put("_ctl0:ImageButton1.y", "10"); + } + + public static HttpRequest loginRequest(String username, String password, SolvedImageCaptcha captcha) { + Map params = new HashMap<>(7); + params.putAll(CONST_PARAMS); + params.put("_ctl0:txtusername", username); + params.put("_ctl0:txtpassword", password); + params.put("_ctl0:txtyzm", captcha.getResult()); + + byte[] requestData = StringUtil.generateQueryString(params).getBytes(StandardCharsets.UTF_8); + + return makeHttpRequest(Graduate.GRADUATE_LOGIN_API, requestData); + } + + public static HttpRequest studentInfoRequest(String cookie) { + return makeHttpRequest(Graduate.GRADUATE_STUDENT_INFO_API, null, cookie); + } + + public static HttpRequest courseTableRequest(String cookie) { + return makeHttpRequest(Graduate.GRADUATE_COURSE_TABLE_API, null, cookie); + } +} diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/request/undergrade/BkjxRequestFactory.java b/mywust-core/src/main/java/cn/linghang/mywust/core/request/undergrade/BkjxRequestFactory.java index 5eccab3..6479be5 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/request/undergrade/BkjxRequestFactory.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/request/undergrade/BkjxRequestFactory.java @@ -22,16 +22,16 @@ public class BkjxRequestFactory extends RequestFactory { public static HttpRequest examScoreInfoRequest(String cookies, String time, String courseKind, String courseName) { FormBodyBuilder formBodyBuilder = new FormBodyBuilder(); // 开课时间(学期) - formBodyBuilder.addQueryParam("kksj", time); + formBodyBuilder.add("kksj", time); // 课程性质 - formBodyBuilder.addQueryParam("kcxz", courseKind); + formBodyBuilder.add("kcxz", courseKind); // 课程名称 - formBodyBuilder.addQueryParam("kcmc", courseName); + formBodyBuilder.add("kcmc", courseName); // 显示方式,这里直接选择全部显示 - formBodyBuilder.addQueryParam("xsfs", "all"); + formBodyBuilder.add("xsfs", "all"); byte[] postData = formBodyBuilder.buildAndToString().getBytes(StandardCharsets.UTF_8); return makeHttpRequest(Bkjx.BKJX_EXAM_INFO_API, postData, cookies); diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/request/undergrade/CourseTableRequestParamFactory.java b/mywust-core/src/main/java/cn/linghang/mywust/core/request/undergrade/CourseTableRequestParamFactory.java index cf24257..61549af 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/request/undergrade/CourseTableRequestParamFactory.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/request/undergrade/CourseTableRequestParamFactory.java @@ -1,10 +1,8 @@ package cn.linghang.mywust.core.request.undergrade; -import cn.linghang.mywust.core.request.RequestFactory; import cn.linghang.mywust.network.entitys.FormBodyBuilder; import java.util.Map; -import java.util.TreeMap; /** *

课表请求参数生成

@@ -27,30 +25,32 @@ public class CourseTableRequestParamFactory { private static final String MAGIC_PARAM_PREFIX_5 = "ACC171586F9245B09C86C589102423B4-"; private static Map generateMagicQueryParam() { - Map magicParams = new TreeMap<>(FormBodyBuilder.REPEATABLE_COMPARATOR); + FormBodyBuilder formBodyBuilder = new FormBodyBuilder(true); for (int i = 0; i < 6; i++) { - magicParams.put("jx0415zbdiv_1", MAGIC_PARAM_PREFIX_0 + i + "-1"); - magicParams.put("jx0415zbdiv_1", MAGIC_PARAM_PREFIX_1 + i + "-1"); - magicParams.put("jx0415zbdiv_1", MAGIC_PARAM_PREFIX_2 + i + "-1"); - magicParams.put("jx0415zbdiv_1", MAGIC_PARAM_PREFIX_3 + i + "-1"); - magicParams.put("jx0415zbdiv_1", MAGIC_PARAM_PREFIX_4 + i + "-1"); - magicParams.put("jx0415zbdiv_1", MAGIC_PARAM_PREFIX_5 + i + "-1"); - - magicParams.put("jx0415zbdiv_2", MAGIC_PARAM_PREFIX_0 + i + "-2"); - magicParams.put("jx0415zbdiv_2", MAGIC_PARAM_PREFIX_1 + i + "-2"); - magicParams.put("jx0415zbdiv_2", MAGIC_PARAM_PREFIX_2 + i + "-2"); - magicParams.put("jx0415zbdiv_2", MAGIC_PARAM_PREFIX_3 + i + "-2"); - magicParams.put("jx0415zbdiv_2", MAGIC_PARAM_PREFIX_4 + i + "-2"); - magicParams.put("jx0415zbdiv_2", MAGIC_PARAM_PREFIX_5 + i + "-2"); + formBodyBuilder + .add("jx0415zbdiv_1", MAGIC_PARAM_PREFIX_0 + i + "-1") + .add("jx0415zbdiv_1", MAGIC_PARAM_PREFIX_1 + i + "-1") + .add("jx0415zbdiv_1", MAGIC_PARAM_PREFIX_2 + i + "-1") + .add("jx0415zbdiv_1", MAGIC_PARAM_PREFIX_3 + i + "-1") + .add("jx0415zbdiv_1", MAGIC_PARAM_PREFIX_4 + i + "-1") + .add("jx0415zbdiv_1", MAGIC_PARAM_PREFIX_5 + i + "-1") + + .add("jx0415zbdiv_2", MAGIC_PARAM_PREFIX_0 + i + "-2") + .add("jx0415zbdiv_2", MAGIC_PARAM_PREFIX_1 + i + "-2") + .add("jx0415zbdiv_2", MAGIC_PARAM_PREFIX_2 + i + "-2") + .add("jx0415zbdiv_2", MAGIC_PARAM_PREFIX_3 + i + "-2") + .add("jx0415zbdiv_2", MAGIC_PARAM_PREFIX_4 + i + "-2") + .add("jx0415zbdiv_2", MAGIC_PARAM_PREFIX_5 + i + "-2"); } - magicParams.put("jx0404id", ""); - magicParams.put("cj0701id", ""); - magicParams.put("zc", ""); - magicParams.put("demo", ""); - magicParams.put("sfFD", "1"); - magicParams.put("kbjcmsid", "9486203B90F3E3CBE0532914A8C03BE2"); + formBodyBuilder + .add("jx0404id", "") + .add("cj0701id", "") + .add("zc", "") + .add("demo", "") + .add("sfFD", "1") + .add("kbjcmsid", "9486203B90F3E3CBE0532914A8C03BE2"); - return magicParams; + return formBodyBuilder.build(); } } diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/ExamInfoApi.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/ExamInfoApi.java index 56f4aa8..3c986a3 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/ExamInfoApi.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/ExamInfoApi.java @@ -4,8 +4,7 @@ import cn.linghang.mywust.core.exception.CookieInvalidException; import cn.linghang.mywust.core.exception.ParseException; import cn.linghang.mywust.core.parser.undergraduate.ExamInfoParser; import cn.linghang.mywust.core.request.undergrade.BkjxRequestFactory; -import cn.linghang.mywust.core.util.BkjxUtil; -import cn.linghang.mywust.model.undergrade.ExamInfo; +import cn.linghang.mywust.model.global.ExamInfo; import cn.linghang.mywust.network.RequestClientOption; import cn.linghang.mywust.network.Requester; import cn.linghang.mywust.network.entitys.HttpRequest; diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/StudentInfoApi.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/StudentInfoApi.java index 80e828c..264f789 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/StudentInfoApi.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/StudentInfoApi.java @@ -4,8 +4,7 @@ import cn.linghang.mywust.core.exception.CookieInvalidException; import cn.linghang.mywust.core.exception.ParseException; import cn.linghang.mywust.core.parser.undergraduate.StudentInfoPageParser; import cn.linghang.mywust.core.request.undergrade.BkjxRequestFactory; -import cn.linghang.mywust.core.util.BkjxUtil; -import cn.linghang.mywust.model.undergrade.StudentInfo; +import cn.linghang.mywust.model.global.StudentInfo; import cn.linghang.mywust.network.RequestClientOption; import cn.linghang.mywust.network.Requester; import cn.linghang.mywust.network.entitys.HttpRequest; diff --git a/mywust-model/src/main/java/cn/linghang/mywust/captcha/SolvedImageCaptcha.java b/mywust-model/src/main/java/cn/linghang/mywust/captcha/SolvedImageCaptcha.java new file mode 100644 index 0000000..05c22d0 --- /dev/null +++ b/mywust-model/src/main/java/cn/linghang/mywust/captcha/SolvedImageCaptcha.java @@ -0,0 +1,25 @@ +package cn.linghang.mywust.captcha; + +import lombok.Data; + +/** + * 已处理的图片验证码 + */ +@Data +public class SolvedImageCaptcha { + /** + * 和验证码绑定的信息,如cookie,某种id等 + */ + private String bindInfo; + + /** + * 验证码验证数据 + */ + private String result; + + public SolvedImageCaptcha(UnsolvedImageCaptcha unsolvedImageCaptcha) { + this.bindInfo = unsolvedImageCaptcha.getBindInfo(); + } + + private void setBindInfo(String bindInfo) {} +} diff --git a/mywust-model/src/main/java/cn/linghang/mywust/captcha/UnsolvedImageCaptcha.java b/mywust-model/src/main/java/cn/linghang/mywust/captcha/UnsolvedImageCaptcha.java new file mode 100644 index 0000000..4123729 --- /dev/null +++ b/mywust-model/src/main/java/cn/linghang/mywust/captcha/UnsolvedImageCaptcha.java @@ -0,0 +1,19 @@ +package cn.linghang.mywust.captcha; + +import lombok.Data; + +/** + * 待处理的图片验证码 + */ +@Data +public class UnsolvedImageCaptcha { + /** + * 和验证码绑定的信息,如cookie,某种id等 + */ + private String bindInfo; + + /** + * 验证码图片,使用byte数组存储 + */ + private byte[] image; +} diff --git a/mywust-model/src/main/java/cn/linghang/mywust/captcha/solver/CaptchaSolver.java b/mywust-model/src/main/java/cn/linghang/mywust/captcha/solver/CaptchaSolver.java new file mode 100644 index 0000000..8aec58d --- /dev/null +++ b/mywust-model/src/main/java/cn/linghang/mywust/captcha/solver/CaptchaSolver.java @@ -0,0 +1,8 @@ +package cn.linghang.mywust.captcha.solver; + +import cn.linghang.mywust.captcha.SolvedImageCaptcha; +import cn.linghang.mywust.captcha.UnsolvedImageCaptcha; + +public interface CaptchaSolver { + SolvedImageCaptcha solve(UnsolvedImageCaptcha unsolvedImageCaptcha); +} diff --git a/mywust-model/src/main/java/cn/linghang/mywust/captcha/solver/LinghangOcrServiceCaptchaSolver.java b/mywust-model/src/main/java/cn/linghang/mywust/captcha/solver/LinghangOcrServiceCaptchaSolver.java new file mode 100644 index 0000000..c3df6c7 --- /dev/null +++ b/mywust-model/src/main/java/cn/linghang/mywust/captcha/solver/LinghangOcrServiceCaptchaSolver.java @@ -0,0 +1,11 @@ +package cn.linghang.mywust.captcha.solver; + +import cn.linghang.mywust.captcha.SolvedImageCaptcha; +import cn.linghang.mywust.captcha.UnsolvedImageCaptcha; + +public class LinghangOcrServiceCaptchaSolver implements CaptchaSolver { + @Override + public SolvedImageCaptcha solve(UnsolvedImageCaptcha unsolvedImageCaptcha) { + return null; + } +} diff --git a/mywust-model/src/main/java/cn/linghang/mywust/captcha/solver/LocalPaddleOcrCaptchaSolver.java b/mywust-model/src/main/java/cn/linghang/mywust/captcha/solver/LocalPaddleOcrCaptchaSolver.java new file mode 100644 index 0000000..d02c511 --- /dev/null +++ b/mywust-model/src/main/java/cn/linghang/mywust/captcha/solver/LocalPaddleOcrCaptchaSolver.java @@ -0,0 +1,11 @@ +package cn.linghang.mywust.captcha.solver; + +import cn.linghang.mywust.captcha.SolvedImageCaptcha; +import cn.linghang.mywust.captcha.UnsolvedImageCaptcha; + +public class LocalPaddleOcrCaptchaSolver implements CaptchaSolver { + @Override + public SolvedImageCaptcha solve(UnsolvedImageCaptcha unsolvedImageCaptcha) { + return null; + } +} diff --git a/mywust-model/src/main/java/cn/linghang/mywust/model/global/Course.java b/mywust-model/src/main/java/cn/linghang/mywust/model/global/Course.java index f975b93..781e79b 100644 --- a/mywust-model/src/main/java/cn/linghang/mywust/model/global/Course.java +++ b/mywust-model/src/main/java/cn/linghang/mywust/model/global/Course.java @@ -55,7 +55,19 @@ public class Course { private ClassRoom classroom; - public static final Map WEEKDAY_MAP = makeWeekdayMap(); + private static final Map WEEKDAY_MAP = makeWeekdayMap(); + + public static int getWeekDayNumber(String weekText) { + return WEEKDAY_MAP.getOrDefault(weekText, 1); + } + + public void setWeekDay(String weekText) { + this.weekDay = getWeekDayNumber(weekText); + } + + public void setWeekDay(int weekDay) { + this.weekDay = weekDay; + } private static Map makeWeekdayMap() { HashMap map = new HashMap<>(7 + 2); diff --git a/mywust-model/src/main/java/cn/linghang/mywust/model/undergrade/ExamInfo.java b/mywust-model/src/main/java/cn/linghang/mywust/model/global/ExamInfo.java similarity index 97% rename from mywust-model/src/main/java/cn/linghang/mywust/model/undergrade/ExamInfo.java rename to mywust-model/src/main/java/cn/linghang/mywust/model/global/ExamInfo.java index c5780fc..771d189 100644 --- a/mywust-model/src/main/java/cn/linghang/mywust/model/undergrade/ExamInfo.java +++ b/mywust-model/src/main/java/cn/linghang/mywust/model/global/ExamInfo.java @@ -1,4 +1,4 @@ -package cn.linghang.mywust.model.undergrade; +package cn.linghang.mywust.model.global; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/mywust-model/src/main/java/cn/linghang/mywust/model/undergrade/StudentInfo.java b/mywust-model/src/main/java/cn/linghang/mywust/model/global/StudentInfo.java similarity index 91% rename from mywust-model/src/main/java/cn/linghang/mywust/model/undergrade/StudentInfo.java rename to mywust-model/src/main/java/cn/linghang/mywust/model/global/StudentInfo.java index d3a5277..f340ae7 100644 --- a/mywust-model/src/main/java/cn/linghang/mywust/model/undergrade/StudentInfo.java +++ b/mywust-model/src/main/java/cn/linghang/mywust/model/global/StudentInfo.java @@ -1,4 +1,4 @@ -package cn.linghang.mywust.model.undergrade; +package cn.linghang.mywust.model.global; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/mywust-network/src/main/java/cn/linghang/mywust/network/entitys/FormBodyBuilder.java b/mywust-network/src/main/java/cn/linghang/mywust/network/entitys/FormBodyBuilder.java index bd823aa..6d7bf1f 100644 --- a/mywust-network/src/main/java/cn/linghang/mywust/network/entitys/FormBodyBuilder.java +++ b/mywust-network/src/main/java/cn/linghang/mywust/network/entitys/FormBodyBuilder.java @@ -33,12 +33,12 @@ public class FormBodyBuilder { this.queryParams = new HashMap<>(initSize); } - public FormBodyBuilder addQueryParams(Map params) { + public FormBodyBuilder add(Map params) { this.queryParams.putAll(params); return this; } - public FormBodyBuilder addQueryParam(String key, String value) { + public FormBodyBuilder add(String key, String value) { this.queryParams.put(key, value); return this; } diff --git a/mywust-test/src/test/java/CourseTableTest.java b/mywust-test/src/test/java/CourseTableTest.java index 8e410fe..ba5daa5 100644 --- a/mywust-test/src/test/java/CourseTableTest.java +++ b/mywust-test/src/test/java/CourseTableTest.java @@ -1,8 +1,6 @@ import cn.linghang.mywust.core.exception.BasicException; import cn.linghang.mywust.core.service.undergraduate.CourseTableApi; -import cn.linghang.mywust.core.service.undergraduate.ExamInfoApi; import cn.linghang.mywust.model.global.Course; -import cn.linghang.mywust.model.undergrade.ExamInfo; import cn.linghang.mywust.network.RequestClientOption; import cn.linghang.mywust.network.Requester; import cn.linghang.mywust.network.okhttp.SimpleOkhttpRequester; diff --git a/mywust-test/src/test/java/ExamInfoTest.java b/mywust-test/src/test/java/ExamInfoTest.java index 473f53d..6bfd0f2 100644 --- a/mywust-test/src/test/java/ExamInfoTest.java +++ b/mywust-test/src/test/java/ExamInfoTest.java @@ -1,6 +1,6 @@ import cn.linghang.mywust.core.exception.BasicException; import cn.linghang.mywust.core.service.undergraduate.ExamInfoApi; -import cn.linghang.mywust.model.undergrade.ExamInfo; +import cn.linghang.mywust.model.global.ExamInfo; import cn.linghang.mywust.network.RequestClientOption; import cn.linghang.mywust.network.Requester; import cn.linghang.mywust.network.okhttp.SimpleOkhttpRequester; diff --git a/mywust-test/src/test/java/StudentInfoPageTest.java b/mywust-test/src/test/java/StudentInfoPageTest.java index 23baa3d..75fe98e 100644 --- a/mywust-test/src/test/java/StudentInfoPageTest.java +++ b/mywust-test/src/test/java/StudentInfoPageTest.java @@ -1,9 +1,6 @@ import cn.linghang.mywust.core.exception.BasicException; -import cn.linghang.mywust.core.parser.undergraduate.StudentInfoPageParser; -import cn.linghang.mywust.core.service.auth.JwcLogin; -import cn.linghang.mywust.core.service.auth.UnionLogin; import cn.linghang.mywust.core.service.undergraduate.StudentInfoApi; -import cn.linghang.mywust.model.undergrade.StudentInfo; +import cn.linghang.mywust.model.global.StudentInfo; import cn.linghang.mywust.network.RequestClientOption; import cn.linghang.mywust.network.Requester; import cn.linghang.mywust.network.okhttp.SimpleOkhttpRequester; diff --git a/pom.xml b/pom.xml index 250dd25..02c5871 100644 --- a/pom.xml +++ b/pom.xml @@ -15,6 +15,15 @@ mywust-util + + + org.jetbrains.externalAnnotations.junit + junit + 4.12-an1 + test + + + 11 11