python第一记,长江雨课堂抓包刷课实战

article/2025/10/26 0:24:08

前言

    发现大学群里好多代刷网课的,确实觉得好多大学网课好费时间,而且没啥用,刚好用来实战一下学的Python,就当练手了。省下来的时间不是又能多敲几行代码😃​

一边省时间,还能学技能,这还不学起来
请添加图片描述

一、长江雨课堂

1.分析视频请求

F12抓包
抓包

播放过程中只有hearbest一个请求,可以确定这个应该就是我们要找的

请求是POST格式,data数据是一个json,通过多个heatbest可以看出是多个观看记录

截取一个分析如下:

c: 1561016
cards_id: 2027472
cc: ""
classroomid: 9763037
cp:424.6
d: 485.4
et: "playing"
fp: 304.5
i: 5
lob: "ykt"
n:"ali-cdn.xuetangx.com"
p:"web"
pg:"2027472_16s0j"
skuid: ""
slide: 44
sp:2
sq: 54
t:"ykt_cards"
tp: 304.5
ts: "1667910647346"
u: 35359786
uip: ""
v: 2027472
v_url: "rain://xtvideo/id/1901324024"

没发现什么加密的字段,​那就一个一个处理
复制第一个1561016,在请求里搜索

在这里插入图片描述
也只有一个请求里搜索到扫一眼可以知道这是课程的列表数据
地址
https://changjiang.yuketang.cn/v2/api/web/courses/list?identity=2
请求里也莫有加密,后面有用到的我们提取保存一下
c的意思应该是class(班级)

get_classroom_id = "https://changjiang.yuketang.cn/v2/api/web/courses/list?identity=2"
classroom_id_response = requests.get(url=get_classroom_id, headers=headers)for ins in json.loads(classroom_id_response.text)["data"]["list"]:your_courses.append({"course_name": ins["course"]["name"],"classroom_id": ins["classroom_id"],"course_sign": ins["university_course_series_id"],"course_id": ins["course"]["id"]})

card_id同上搜索也只有一个请求
地址: https://changjiang.yuketang.cn/v2/api/web/logs/learn/9763037?actype=-1&page=0&offset=20&sort=-1
9763037搜索就可以发现是classroom_id,已经保存过了
在这里插入图片描述
在这里插入图片描述

就是一个课程列表数据
和上面一样有用的数据保存一下

def get_videos_ids(course_name,classroom_id,course_sign):get_homework_ids = "https://changjiang.yuketang.cn/v2/api/web/logs/learn/"+str(classroom_id)+"?actype=-1&page=0&offset=20&sort=-1"homework_ids_response = requests.get(url=get_homework_ids, headers=headers)homework_json = json.loads(homework_ids_response.text)homework_dic = {}try:for i in homework_json["data"]["activities"]:if i['type'] == 14:# 课堂passelif i['type'] == 9:# 公告passelif i['type'] == 2:# 课件homework_dic[i['title']] = {'courseware_id' : i['courseware_id'],'id' : i['id']}print(course_name+"共有"+str(len(homework_dic))+"个作业喔!")return homework_dic
KEYValue说明
cp424.6观看时长(破解点)
d:485.4视频长度
et“playing”操作
fp304.5常量
i5常量
lob“ykt”常量
n“ali-cdn.xuetangx.com”常量
p“web”(观看方式)常量
pg“2027472_16s0j”算个小加密可能
skuid“”常量
slide44视频所在ppt页数
sp2常量
sq54常量
t“ykt_cards”常量
tp304.5常量
ts“1667910647346”13位时间戳
u35359786user_id
uip“”常量
v2027472cards_id
v_url“rain://xtvideo/id/1901324024”地址

差不多都是请求里搜索然后找位置保存,没有什么变化,只有pg后面的一小串要在js里面找,但是是个随机产生的数,可以写死。
可以下一个xhr断点
在这里插入图片描述
段下来之后一个一个看调用堆栈
到resetTimer函数的时候,可以看到参数的构建位置
也可以在这里下断点看一下都是怎么构建的
因为我要找pg, 看到

pg: e.options.id + "_" + u

所以就向上找u
在这里插入图片描述
15760行有定义

var t, i, r, o, n, d, u = Math.floor(1048576 * (1 + Math.random())).toString(36);

2.代码实现

ok所用参数都找到获取方式了接下来就是写代码的时间

# -*- coding: utf-8 -*-
# version 4
# developed by zk chen
import time
import requests
import re
import json
import execjsclass jsFun:def __init__(self):passdef math(self):fun = '''function a(){let u = Math.floor(1048576 * (1 + Math.random())).toString(36);return u;};'''ctx = execjs.compile(fun)return ctx.call("a")
# 以下的cookie复制下面图片中的内容!!!!而且脚本需在登录雨课堂状态下使用
Cookie = "这里复制粘贴Cookie"
# 以下字段不用改,下面的代码也不用改动
user_id = ""
f = jsFun()
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.42','Content-Type': 'application/json','Cookie': Cookie'authority':'changjiang.yuketang.cn','method':'GET','path':'/v2/api/web/courses/list?identity=2','referer':'https://changjiang.yuketang.cn/v2/web/personal/info','sec-fetch-dest':'empty','sec-fetch-mode':'cors','sec-fetch-site':'same-origin',# 'university-id':'2727','x-csrftoken':'LE6xYWZ4rWN3UFHHDFkiykMBvffI4sCf','dnt' : '1'
}leaf_type = {"video": 0,"homework": 6,"exam": 5,"recommend": 3,"discussion": 4
}def get_video_id_list(cards_id,classroomid):url = f'https://changjiang.yuketang.cn/v2/api/web/cards/detlist/{cards_id}?classroom_id={classroomid}'js = json.loads(requests.get(url=url, headers=headers).text)List = []num =1for ins in js['data']['Slides']:for i in ins['Shapes']:if 'playurl' in i:if i['file_type'] == 1:List.append((i['URL'],str(num)))num += 1return List , numdef one_video_watcher(video_name,cid,user_id,classroomid,cards_id):classroomid = str(classroomid)id_list,num = get_video_id_list(cards_id,classroomid)for url_id,n in id_list:url = "https://changjiang.yuketang.cn/video-log/heartbeat/"get_url = f"https://changjiang.yuketang.cn/video-log/get_video_watch_progress/?user_id={user_id}&cid={cid}&video_type=ykt_cards&classroom_id={classroomid}&cards_id={cards_id}&v_url={url_id}&slide={n}"headers['xtbz'] = 'ykt'progress = requests.get(url=get_url, headers=headers)if_completed = '0'# while 1:try:js = json.loads(progress.text)[str(n) + ":"+re.search(r'[0-9]+',url_id).group()]videolength = js['video_length']except:print("视频" + str(n) + " " + video_name + "学习失败!")continue# time.sleep(10)# continuetry:if_completed = re.search(r'"completed":(.+?),', progress.text).group(1)except:passif if_completed == '1':print(video_name+"已经学习完毕,跳过")continueelse:print(video_name+",尚未学习,现在开始自动学习")video_frame = 0val = 0learning_rate = 20t = time.time()timestap = int(round(t * 1000))while val != "1.0" and val != '1':heart_data = []for i in range(50):heart_data.append({"i": 5,"et": "loadeddata","p": "web","n": "ali-cdn.xuetangx.com","lob": "ykt","cp": video_frame,"fp": 0,"tp": 0,"sp": 1,"ts": str(timestap),"u": int(user_id),"uip": "","c": cid,"v": cards_id,"skuid": '',"classroomid": classroomid,"cc": '',"d": videolength,"pg": f"{cards_id}_"+f.math(),"sq": 2,"t": "ykt_cards","cards_id": cards_id,"slide": n,"v_url": url_id})video_frame += learning_ratemax_time = int((time.time() + 3600) * 1000)timestap = min(max_time, timestap+1000*15)data = {"heart_data": heart_data}r = requests.post(url=url,headers=headers,json=data)try:error_msg = json.loads(r.text)["message"]if max_time< timestap+1000*15:video_frame = 0except:passtry:delay_time = re.search(r'Expected available in(.+?)second.', r.text).group(1).strip()print("由于网络阻塞,万恶的雨课堂,要阻塞" + str(delay_time) + "秒")time.sleep(float(delay_time) + 0.5)video_frame = 0print("恢复工作啦~~")r = requests.post(url=submit_url, headers=headers, data=data)except:passprogress = requests.get(url=get_url,headers=headers)tmp_rate = re.search(r'"rate":(.+?)[,}]',progress.text)if tmp_rate is None:return 0val = tmp_rate.group(1)print("学习进度为:" + str(float(val)*100) + "%/100%" + " last_point: " + str(video_frame))time.sleep(0.7)print("视频"+str(n)+" "+video_name+"学习完成!")return 1def get_videos_ids(course_name,classroom_id,course_sign):get_homework_ids = "https://changjiang.yuketang.cn/v2/api/web/logs/learn/"+str(classroom_id)+"?actype=-1&page=0&offset=20&sort=-1"homework_ids_response = requests.get(url=get_homework_ids, headers=headers)homework_json = json.loads(homework_ids_response.text)homework_dic = {}try:for i in homework_json["data"]["activities"]:if i['type'] == 14:# 课堂passelif i['type'] == 9:# 公告passelif i['type'] == 2:# 课件homework_dic[i['title']] = {'courseware_id' : i['courseware_id'],'id' : i['id']}print(course_name+"共有"+str(len(homework_dic))+"个作业喔!")return homework_dicexcept:print("fail while getting homework_ids!!! please re-run this program!")raise Exception("fail while getting homework_ids!!! please re-run this program!")if __name__ == "__main__":your_courses = []# 首先要获取用户的个人ID,即user_id,该值在查询用户的视频进度时需要使用user_id_url = "https://changjiang.yuketang.cn/v/course_meta/user_info"id_response = requests.get(url=user_id_url, headers=headers)id_response.encoding="utf-8"try:user_id = re.search(r'"user_id": ([0-9]+),', id_response.text).group(1)except:print("也许是网路问题,获取不了user_id,请试着重新运行")raise Exception("也许是网路问题,获取不了user_id,请试着重新运行!!! please re-run this program!")# 然后要获取教室idget_classroom_id = "https://changjiang.yuketang.cn/v2/api/web/courses/list?identity=2"submit_url = "https://gruestc.yuketang.cn/mooc-api/v1/lms/exercise/problem_apply/?term=latest&uv_id=3194"headers["referer"] = 'https://changjiang.yuketang.cn/v2/web/index?date=1666686775760&newWeb=1'classroom_id_response = requests.get(url=get_classroom_id, headers=headers)try:for ins in json.loads(classroom_id_response.text)["data"]["list"]:your_courses.append({"course_name": ins["course"]["name"],"classroom_id": ins["classroom_id"],"course_sign": ins["university_course_series_id"],"course_id": ins["course"]["id"]})except Exception as e:print("fail while getting classroom_id!!! please re-run this program!")raise Exception("fail while getting classroom_id!!! please re-run this program!")# 显示用户提示for index, value in enumerate(your_courses):print("编号:"+str(index+1)+" 课名:"+str(value["course_name"]))number = input("你想刷哪门课呢?请输入编号。输入0表示全部课程都刷一遍\n")if int(number)==0:#0 表示全部刷一遍for ins in your_courses:homework_dic = get_videos_ids(ins["course_name"],ins["classroom_id"], ins["course_sign"])for one_video in homework_dic.items():one_video_watcher(one_video[0],ins["course_id"],user_id,ins["classroom_id"],cards_id=homework_dic[one_video])else:#指定序号的课程刷一遍number = int(number)-1homework_dic = get_videos_ids(your_courses[number]["course_name"],your_courses[number]["classroom_id"],your_courses[number]["course_sign"])for one_video in homework_dic.items():one_video_watcher(one_video[0], your_courses[number]["course_id"], user_id, your_courses[number]["classroom_id"],cards_id = one_video[1]['courseware_id'])

cookie替换一下
请添加图片描述

总结

大体就是播放视频,抓包,找参数,在请求里搜素,加密了就下断点看实现。
!!!主要是思路,还有一些雨课堂,学习通,mooc,什么的都差不多的。

http://chatgpt.dhexx.cn/article/7mAigVAX.shtml

相关文章

在哪能免费学习python

1、中国大学MOOC 课程很多都是高校开设的&#xff0c;比较推荐南京大学的《用python玩转数据》&#xff0c;从最基础的开始讲&#xff0c;由深入浅&#xff0c;非专业的伙伴也可以听懂。&#xff08;文末送福利&#xff09; 2、Python中文学习大本营 所有学习资料和教程都是…

python-seleium实现珞珈在线网课辅助观看功能

《武汉大学安全教育前置课程》网课观看辅助.py脚本 即将来到珞珈山的萌新们&#xff0c;在到校前&#xff0c;你是不是需要完成《武汉大学安全教育前置课程》&#xff1f;视频好多&#xff0c;一个一个来点击观看是不是有些疲累&#xff1f;快来看看这个脚本叭&#xff01; 本…

python 课程学习

文章目录 目录 文章目录 前言&#xff1a; 一、安装anconda软件​二、使用步骤 2.1.询物理地址 2.2&#xff1a;复制讲义到该文件地址 2.3&#xff1a;OS模块学习 2.3.1 创建地址采用 os.mkdir() 2.3.2 python os.path 的使用 Python os.path() 模块 | 菜鸟教程 (runo…

免费python网络课程-python网络课程

广告关闭 腾讯云双11爆品提前享&#xff0c;精选热门产品助力上云&#xff0c;云服务器首年88元起&#xff0c;买的越多返的越多&#xff0c;最高满返5000元&#xff01; machine learning course with pythonby machine learningmindset简介本项目的目的是提供一个全面而简单…

python免费课程全套-为了学习Python,我汇总了这10个免费的视频课程!

毫无疑问,Python是目前世界上***的编程语言,它***的优势在于它将越多越多的人带入了编程领域。 近年来,学习Python的人比学习其他任何语言的人都多,许多人学Python是为了它背后的数据科学和机器学习库,当然,也有一些人学习用于Web开发的Python,有些人则学习用于编写脚本…

全套Python课程~

今天是元宵节&#xff0c;元宵节过后很多朋友就要开学啦~提前祝大家开学快乐&#xff01; 今天给大家分享一套详细全面的Python系统课程&#xff0c;总共有637集&#xff0c;从入门到精通。大家可以先收藏下开学后后慢慢学&#xff01; 【Python基础】Python_PYTHON入门_零基础…

Python进阶——网课不愁系列AI换脸技术

俗话说的好&#xff1a;网络一线牵&#xff0c;珍惜这段缘&#xff01; 网络的水很深&#xff0c;年轻人你把握不住&#xff0c;众所周知照片是可以P的&#xff0c;但是“视频”是“P”不了的&#xff08;狗头保命&#xff09; 谁能想到AI换脸竟然如此便捷&#xff0c;在Python…

Python开发的Web在线学习教育培训网课系统

目 录 摘 要 I Abstract II 第1章 绪论 1 1.1 课题研究背景 1 1.2 课题研究目标与意义 2 1.3 课题研究内容及思路 2 第2章 系统需求分析 4 2.1系统的性能要求 4 2.2系统功能需求分析 4 2.2.1功能划分 4 2.2.2功能描述 7 2.3技术可行性分析 9 2.4相关技术简介 10 2.4.1 B/S体系相…

自学python哪个网课好,网课学python学的好吗

Python可以自学吗&#xff1f;有哪些不错的网课&#xff1f; 可以自学的&#xff0c;需要依据每个人的情况来决定&#xff0c;想要自学python对各方面有一定要求的&#xff0c;比如说基础好、自学能力强、理解能力强&#xff0c;这种情况是可以选择自学python的&#xff1b;相…

python免费网课-Python网课推荐——免费学习Python编程

对于想要学习python的初学者,面对网上大量的学习素材无从下手。今天小编就整理了一份详细的python教学视频合集,希望能为初学者提供一些学习的方向。 1.python入门 课程推荐:零基础入门学习Python 《小甲鱼零基础入门学习Python视频基础》(python教学版本:3.3.2)讲的是…

推荐一个学习python的网课,适合零基础

前言 如果你是零基础学习 Python&#xff0c;可以考虑以下几个网课&#xff1a; Codecademy Python 课程&#xff1a;该课程适合初学者&#xff0c;具有互动式的学习体验&#xff0c;可以让你快速掌握 Python 的基本知识。Udemy Python 从入门到精通课程&#xff1a;这个课程…

spring8-getBean()方法使用

&#xff1b;&#xff1a;getBean使用&#xff0c;要传数据&#xff0c;一个是字符串&#xff0c; 就是文件里的UserService 而这里的UserService就是我们配置文件的id&#xff1a;&#xff0c;第一个API 第二个API可以传入一个字节码类型。 如果某一个容器存在多个&#xff…

spring框架ApplicationContext的getBean()方法的详解

点击上方蓝字"优派编程"选择“加为星标”&#xff0c;第一时间关注原创干货 spring框架&#xff1a;接口ApplicationContext中的getBean()方法的详解 http://wp.fang1688.cn/study/318.html 我们知道可以通过ApplicationContext的getBean方法来获取Spring容器中已初始…

【细读Spring Boot源码】Spring如何获取一个Bean?BeanFactory的getBean方法

前言 在读refresh(context);时&#xff0c;finishBeanFactoryInitialization(beanFactory);中beanFactory.preInstantiateSingletons();用于实例化剩余所有的non-lazy-init的单例。这里包含了前置处理器和后置处理器 这里面就用到了本文主题getBean(beanName); 下面具体看看这…

Spring中关于getBean()报强制转化错误

在自学Spring时&#xff0c;在使用getBean()时&#xff0c;会报com.sakura.dao.impl.BookDaoImpl cannot be cast to com.sakura.dao.BookDao at com.sakura.App2.main(App2.java:19) 这个错误表示&#xff0c;不能将一个实现类BookDaoImpl类强转为BookDao接口。这个错&#…

spring源码解读之getBean方法(一)

前言 大家使用spring&#xff0c;最常接触到的就是bean&#xff0c;大家也知道spring中用一句getBean就能取出一个实例化好的bean&#xff0c;这个bean是属于IOC容器管理的&#xff0c;那么大家有没有看过getBean方法的源码呢&#xff0c;知不知道spring容器到底是怎么得到一个…

Spring源码之getBean(获取 bean)方法(一)解读

目录 测试类一个简单的测试类对于 ApplicationContext 和 ClassPathXmlApplicationContext 类图如下getBean() 源码解读查看 AbstractApplicationContext 中的 getBean 方法查看 AbstractBeanFactory 的 doGetBean 方法看 doGetBean 方法的流程图分析doGetBean 方法的主要流程 …

JavaBean(set和get方法)

JavaBean的规范 类中所有的成员属性都是私有&#xff0c;也就是 private 来修饰 提供一个公共无参数的构造方法 为所有私有的属性提供公共的 set 和 get 方法。 set方法 set 方法是有参数无返回值的&#xff0c;目的是通过 set 方法给 javabean 中的私有属性赋值&#xff0c;…

getBean方法源码

一、 三个API // 根据name获取bean Override public Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false); }// 根据name获取bean&#xff0c;如果获取到的bean和指定类型不匹配&#xff0c;则抛出异常 Override public <T>…

详解Spring中getBean()方法

我们日常会经常使用getBean()方法从spring容器中获取我们需要的bean。那么&#xff0c;getBean()方法是怎么一步步完成从spring容器中获取bean的呢&#xff1f; 下面我们就通过源码分析一下。 一、主要代码分析 基于&#xff1a;spring5.1 入口&#xff1a;AbstractBeanFactory…