From 94b9d6ffb139b23f5872abc7486fad19494daae7 Mon Sep 17 00:00:00 2001 From: shuyongqiang Date: Tue, 3 Aug 2021 16:51:40 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0vip=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E8=AE=A2=E9=98=85=E6=8C=87=E5=AE=9A=E5=88=86=E7=B1=BB=E7=9A=84?= =?UTF-8?q?=E8=AF=BE=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../online/githuboy/lagou/course/App.java | 6 +- .../lagou/course/request/HttpAPI.java | 77 +++++++++++++++++++ .../githuboy/lagou/course/support/Course.java | 42 ++++++++++ .../lagou/course/utils/ConfigUtil.java | 6 ++ src/main/resources/config/config.properties | 3 + 5 files changed, 133 insertions(+), 1 deletion(-) diff --git a/src/main/java/online/githuboy/lagou/course/App.java b/src/main/java/online/githuboy/lagou/course/App.java index 555214b..3a39eb8 100644 --- a/src/main/java/online/githuboy/lagou/course/App.java +++ b/src/main/java/online/githuboy/lagou/course/App.java @@ -12,6 +12,7 @@ import java.io.File; import java.io.IOException; import java.util.List; +import java.util.Set; /** * 启动类 @@ -35,7 +36,10 @@ public static void main(String[] args) throws IOException, InterruptedException List allCoursePurchasedRecordForPC = CollectionUtil.isNotEmpty(ConfigUtil.getCourseIds()) ? ConfigUtil.getCourseIds() : Course.getAllCoursePurchasedRecordForPC(); - + + // 如果是vip,可以选择自动订阅课程。 + Set courseIds = Course.drawCourse(); + allCoursePurchasedRecordForPC.addAll(courseIds) ; log.info("开始下载课程 专栏ID列表:{}", allCoursePurchasedRecordForPC); //倒叙 //Collections.reverse(allCoursePurchasedRecordForPC); diff --git a/src/main/java/online/githuboy/lagou/course/request/HttpAPI.java b/src/main/java/online/githuboy/lagou/course/request/HttpAPI.java index 788aab0..1458877 100644 --- a/src/main/java/online/githuboy/lagou/course/request/HttpAPI.java +++ b/src/main/java/online/githuboy/lagou/course/request/HttpAPI.java @@ -14,7 +14,9 @@ import java.text.MessageFormat; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; /** @@ -31,6 +33,8 @@ public class HttpAPI { private final static String COURSE_INFO_API = "https://gate.lagou.com/v1/neirong/kaiwu/getCourseLessons?courseId={0}"; private final static String COURSE_COMMENT_LIST_API = "https://gate.lagou.com/v1/neirong/course/comment/getCourseCommentList?courseId={0}&lessonId={1}&pageNum={2}&needCount=true"; private final static String PURCHASED_COURSE_API = "https://gate.lagou.com/v1/neirong/kaiwu/getAllCoursePurchasedRecordForPC?t={0}"; + private final static String COURSE_LIST_API = "https://gate.lagou.com/v1/neirong/edu/homepage/getCourseListV2?isPc=true&t={0}"; + private final static String COURSE_DRAW_API = "https://gate.lagou.com/v1/neirong/edu/member/drawCourse?courseId={0}"; public static CourseInfo getCourseInfo(String courseId) { String url = MessageFormat.format(COURSE_INFO_API, courseId); @@ -197,4 +201,77 @@ public static PurchasedCourseRecord getPurchasedCourseRecord() { } return record; } + + /** + * 列出所有的课程 + * + * @return Map> 课程类别->课程id集合 + */ + public static Map> listCourse() { + String url = MessageFormat.format(COURSE_LIST_API, System.currentTimeMillis()); + String body = HttpUtils.get(url, CookieStore.getCookie()).header("x-l-req-header", "{deviceType:1}").execute().body(); + JSONObject json = JSON.parseObject(body); + Integer state = json.getInteger("state"); + if (state != null && state != 1) { + log.info("获取所有课程失败:json:{}", body); + throw new RuntimeException("获取所有课程失败:" + json.getString("message")); + } + + JSONObject result = json.getJSONObject("content"); + JSONArray cardListJsonArray = result.getJSONArray("contentCardList"); + Map> map = new HashMap>(); + + for (int i = 0; i < cardListJsonArray.size(); i++) { + JSONObject card = cardListJsonArray.getJSONObject(i); + JSONArray courseList = card.getJSONArray("courseList"); + for (int j = 0; j < courseList.size(); j++) { + JSONObject course = courseList.getJSONObject(j); + + JSONArray classifyIds = course.getJSONArray("classifyIds"); + if (classifyIds != null) { + + for (int k = 0; k < classifyIds.size(); k++) { + String classify = classifyIds.get(k).toString(); + List list = map.get(classify); + if (list == null) { + list = new ArrayList<>(); + map.put(classify, list); + } + list.add(course.getString("id")); + } + } + } + } + return map; + + } + /** + * vip订阅课程 + * @param courseId + */ + public static void drawCourse(String courseId) { + + String url = MessageFormat.format(COURSE_DRAW_API, courseId); + log.debug("订阅课程:{},url:{}", courseId, url); + HttpRequest httpRequest = HttpUtils.get(url, CookieStore.getCookie()).header("x-l-req-header", "{deviceType:1}"); + String body; + try { + body = httpRequest.execute().body(); + } catch (Exception e) { + try { + Thread.sleep(RandomUtil.randomLong(500L, TimeUnit.SECONDS.toMillis(1))); + } catch (InterruptedException interruptedException) { + log.error(interruptedException.getMessage(), interruptedException); + } + log.info("订阅课程 重试1次"); + body = httpRequest.execute().body(); + } + + JSONObject jsonObject = JSON.parseObject(body); + Integer state = jsonObject.getInteger("state"); + if (state != null && state != 1) { + log.info("订阅课程失败:json:{}", body); + throw new RuntimeException("订阅课程失败:" + jsonObject.getString("message")); + } + } } diff --git a/src/main/java/online/githuboy/lagou/course/support/Course.java b/src/main/java/online/githuboy/lagou/course/support/Course.java index 7c0e643..aeb81b5 100644 --- a/src/main/java/online/githuboy/lagou/course/support/Course.java +++ b/src/main/java/online/githuboy/lagou/course/support/Course.java @@ -2,11 +2,16 @@ import online.githuboy.lagou.course.domain.PurchasedCourseRecord; import online.githuboy.lagou.course.request.HttpAPI; +import online.githuboy.lagou.course.utils.ConfigUtil; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; /** * @author eric @@ -36,4 +41,41 @@ public static List getAllCoursePurchasedRecordForPC() { log.info("一共有{}门课程", courseIdSets.size()); return courseIdSets; } + /** + * 获取指定类别的课程id + * @param classifyIds 课程类别集合 + * @return + */ + public static Set getAllCourseVipForPC(List classifyIds) { + Set set = new HashSet(); + Map> courses = HttpAPI.listCourse(); + + if (classifyIds.size() == 1 && classifyIds.get(0).equals("0")) { + for (List list : courses.values()) { + set.addAll(list); + } + } else { + for (String classify : classifyIds) { + set.addAll(courses.get(classify)); + } + } + + return set; + } + /** + * vip自动订阅指定类别的课程 + * @return 成功订阅的课程id + */ + public static Set drawCourse() { + + List allCoursePurchasedRecordForPC = Course.getAllCoursePurchasedRecordForPC(); + // 所有指定订阅的课程 + List classifyIds = ConfigUtil.getClassifyIds(); + Set courseIds = Course.getAllCourseVipForPC(classifyIds); + courseIds.removeAll(allCoursePurchasedRecordForPC) ; + for (String courseId : courseIds) { + HttpAPI.drawCourse(courseId); + } + return courseIds ; + } } diff --git a/src/main/java/online/githuboy/lagou/course/utils/ConfigUtil.java b/src/main/java/online/githuboy/lagou/course/utils/ConfigUtil.java index c504756..8d9a392 100644 --- a/src/main/java/online/githuboy/lagou/course/utils/ConfigUtil.java +++ b/src/main/java/online/githuboy/lagou/course/utils/ConfigUtil.java @@ -61,6 +61,12 @@ public static List getCourseIds() { Set set = ArrayUtils.isEmpty(split) ? new HashSet<>() : new HashSet<>(Arrays.asList(split)); return set.stream().map(String::trim).collect(Collectors.toList()); } + public static List getClassifyIds() { + String courseIds = readValue("classifyIds"); + String[] split = StringUtils.split(courseIds, ","); + Set set = ArrayUtils.isEmpty(split) ? new HashSet<>() : new HashSet<>(Arrays.asList(split)); + return set.stream().map(String::trim).collect(Collectors.toList()); + } public static void main(String[] args) { System.out.println(ConfigUtil.readValue("mp4_dir")); diff --git a/src/main/resources/config/config.properties b/src/main/resources/config/config.properties index 0842902..f8b6f6e 100644 --- a/src/main/resources/config/config.properties +++ b/src/main/resources/config/config.properties @@ -10,5 +10,8 @@ mp4_xunlianying_dir=~/Downloads/lagou-xunlianying-mp4 courseIds= # 要排除的课程列表,用逗号分割 格式例如:6,16,356 716_Python入门与实战-至尊 这个视频有毒 remove_course=716 +#vip账号订阅指定类别的课程,用逗号分割,如果不指定,不会进行自动订阅,格式例如:1,3 ;如果是单独的0表示订阅所有 +#类别说明:1 后端&架构 2 前端&移动 3 数据分析 4 产品&设计 5 市场&运营 6 大数据&AI 7 测试&运维 8 职场&管理 9 学生&入门 +classifyIds= # 视频下载超时(分钟)默认10分钟, 如果下载的文件可能较大,超过10分钟,那么可以把时间调长 mp4_download_timeout=10 \ No newline at end of file