吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 8624|回复: 48
收起左侧

[其他原创] 中国大学 MOOC 免费课程及课件爬虫

  [复制链接]
729 发表于 2020-11-23 14:33
本帖最后由 729 于 2020-11-23 19:10 编辑

该源码 获取的是下载地址(免费的课程视频以及课件  付费课程的PDF文件 视频是经过加密的) 没有进行下载 需要下载的可以调用返回的下载地址即可
老实说 我不会排版 也是第一次写分析过程 所以有啥问题就不要见怪了哈

分析过程

PDF链接分析

进入课程主页并全程使用fiddler进行监视

1.png

随便点击文档 在网页右下角中有对应的文档下载 获取下载链接

2.png

使用fiddler 进行搜索查找链接的源头

3.png

找到下载链接的源头 获取其头部信息 进行分析

4.png 5.png

查找两个数据的来源 分析信息

6.png
1.分析信息得知 返回的数据是分段的 并且当contentType=3的时候 对应的是PDF文件 其中数据中有许多参数各有其他使用(name之类的) 可以自行判断
2.分析头部信息

7.png 8.png

获取termID

9.png

PDF:
1.在访问课程主页的时候获取termID
2.使用termID获取所用的课程PDF文件对应的contentID已经s.x.id POST访问(https://www.icourse163.org/dwr/call/plaincall/CourseBean.getLastLearnedMocTermDto.dwr)
3.获取对应的contentID以及s.x.id后POST访问('https://www.icourse163.org/dwr/call/plaincall/CourseBean.getLessonUnitLearnVo.dwr')即可获得对应的下载链接

视频链接获取

随便点击一个视频进行观看 之前的抓包可以不用清理那么快 因为也需要
获取对应的视频下载URL(使用的是IDM下载器 所以我这直接出现 )

10.png
如果没有IDM直接获取到的也可以进行分析
当视频播放的时候fidell可以抓包到连续的访问 类型相同的

11.png

分析他们的链接 看着相似 找出不同部分进行搜索,发现全部来自同一个访问的返回值

12.png

对访问的URL进行查找(实际上这个URL与IDM下载器抓取到的URL是一致的 )里面有好几个URL 对应的是不同的视频清晰度以及格式 可以全部下载试一下

13.png
发现其中的URL是简单的GET访问 分析其数据来源 VIDEOID signature
发现VideoID也属于上面PDF之前的全部课程ID里面 对应contentId

14.png

进行sigature头部数据分析
进行搜索csrfkey来自访问官网时候得到的cookies里面的NTESSTUDYSI值
bizId是contentI对应的s.x.id
15.png
视频URL获取:
1.进行官网访问获取csrfkey值
2获取所有课程contentId 以及对应的s.x.id(文件ID)
3.根据s.x.id获取对应的signature签名
4.根据获取到的signature获取所有清晰度以及格式的视频下载链接 打开即可下载


---

获取课程主ID  ##课程主页termId

key_id=re.search(r'\d+',re.search(r'id : ".+"',requests.get('课程主页URL').text).group()).group()`


获取视频目录以及ID

payloaddata={'callCount':1,
'scriptSessionId':'${scriptSessionId}190',
'c0-scriptName':'CourseBean',
'c0-methodName':'getMocTermDto',
'c0-id':'a',
'c0-param0':1207358202,##课程目录ID
'c0-param1':0,
'c0-param2':'true',
'batchId':'1605715313492'}
r=requests.post('https://www.icourse163.org/dwr/call/plaincall/CourseBean.getLastLearnedMocTermDto.dwr',data=payloaddata)
r.text  #这是获得课程的所有视频的ID以及所有文档的ID
contentType=null##一个章节
contentType=3##获得的是文档
contentType=2##单元测试或其他(反正不是文件)
contentType=1##获取视频


文档下载可直接获得

data={
'callCount':1,
'scriptSessionId':'${scriptSessionId}190',
'c0-scriptName':'CourseBean',
'c0-methodName':'getLessonUnitLearnVo',
'c0-id':0,
'c0-param0':'1214812409',##contentId
'c0-param1':3,
'c0-param2':0,
'c0-param3':'1216200842',##s.x.id
'batchId':'1605720752677',}
url='https://www.icourse163.org/dwr/call/plaincall/CourseBean.getLessonUnitLearnVo.dwr'
r=requests.post('url',data=data)  ##取得其中的textOrigUrl即是下载链接


视频地址获取步骤:

1.进入官网获取cookie 其中cookie中的NTESSTUDYSI值是csrfkey值 这是官网防止跨域访问(https://www.icourse163.org)
2.获取对应的signature   ('https://www.icourse163.org/web/j/resourceRpcBean.getResourceToken.rpc?csrfKey='+csrfkey)##POST访问
    data={'bizId':1260493290,#s.x.id
             'bizType':1,
             'contentType':1}
3.获取对应的视频m3u8的URL ('https://vod.study.163.com/eds/api/v1/vod/video?videoId='+contentId+'&signature='+signature+'&clientType=1')#GET获取
            clienType=1 #按照上面的获取来说应该是一个视频的标志
            返回值需要的有:videoUrl  以及ak 里面有好几个videoUrl对应不同的清晰度以及格式

源码


[Python] 纯文本查看 复制代码
#encoding:utf-8
import requests
import re
from requests import Session
import json

class Mooc:

    def __init__(self,url):
        self.url=url
        self.termId=re.search(r'\d+',re.search(r'termId : ".+"',requests.get(url).text).group()).group()
        self.__GetAllId()

    def __GetAllId(self):
        self.dic={}##总字典
        dic_con={}##每个小章节字典
        file_number=0##每个小章节的文件数
        AllId_url='https://www.icourse163.org/dwr/call/plaincall/CourseBean.getLastLearnedMocTermDto.dwr'##返回课程文件ID以及内容ID
        payloaddata={'callCount':1,
                     'scriptSessionId':'${scriptSessionId}190',
                     'c0-scriptName':'CourseBean',
                     'c0-methodName':'getMocTermDto',
                     'c0-id':'a',
                     'c0-param0':self.termId,##课程目录ID
                     'c0-param1':0,
                     'c0-param2':'true',
                     'batchId':'1605715313492'}##随便啦长度一样的数字吧大概
        r=requests.post(AllId_url,data=payloaddata)##
        list_re=re.compile(r'contentId=.+').findall(r.text)##将返回的数据进行处理分段
        for d in list_re:##遍历每段数据 获取参数值
            contentId=re.search(r'contentId=\d+',d)
            contentType=re.search(r'\d+',re.search(r'contentType=\d',d).group()).group()##文件格式
            file_id=re.search(r'\d+',re.search(r'\.id=\d+',d).group()).group()##文件ID
            name=re.search(r'".+"',re.search(r'name=.+"',d).group()).group().encode('utf8').decode('unicode_escape')
            if contentId and not re.search(r'isTestChecked',d):##确认是否有内容ID 以及是否是课件或者视频
                file_number+=1
                contentId=re.search(r'\d+',contentId.group()).group()
                dic_con={'contentId':contentId,'contentType':contentType,'file_id':file_id,'name':name}
                self.dic[name_all][name_content][file_number]=dic_con
            else:
                if re.search(r'published=true',d):##大章节的确认
                    name_all=name##大章节名字
                    self.dic[name_all]={}
                else:
                    if re.search(r'isTestChecked=false',d):##小章节的确认
                        name_content=name##小章节名字
                        file_number=0##小章节文件数量
                        self.dic[name_all][name_content]={}
#dic格式
#{'第一大章节名':{'第一小章节名':{1(文件数):{'contentId': '课程ID', 'contentType': '文件格式', 'file_id': '文件ID','name':'文件名'},...},
#                 '第二小章节名':...},
# '第二章大章节名':...}

                        
    def GetPdf(self):
        pdf_dic={}
        Pdf_url='https://www.icourse163.org/dwr/call/plaincall/CourseBean.getLessonUnitLearnVo.dwr'
        data={
        'callCount':1,
        'scriptSessionId':'${scriptSessionId}190',
        'c0-scriptName':'CourseBean',
        'c0-methodName':'getLessonUnitLearnVo',
        'c0-id':0,
        'c0-param0':'contentId',##contentId
        'c0-param1':3,
        'c0-param2':0,
        'c0-param3':'文件ID',##文件ID
        'batchId':'1606049296413',}
        for p in self.dic.items():
            for d in p[1].items():
                for f in d[1].items():
                    if f[1]['contentType']=='3':
                        data['c0-param0']=f[1]['contentId']
                        data['c0-param3']=f[1]['file_id']
                        r=requests.post(Pdf_url,data=data)  ##取得其中的textOrigUrl即是下载链接
                        pdf_dic[d[0]]=re.search(r'textUrl:".+"',r.text).group()[9:-1]
        return pdf_dic
## pdf_dic格式
## pdf_dic={'PDF文件名':下载地址,...}  返回的是下载地址 没有进行下载 需要的可以自己写一个用来下载的即可

    def GetTs(self):
        ts_dic={}
        s=Session()
        s.get('https://www.icourse163.org')
        csrfkey=s.cookies['NTESSTUDYSI'] 
        data={'bizId':1260493290,#contentId
                 'bizType':1,
                 'contentType':1}    
        for v in self.dic.items():#dic.keys()每个大章节的名字 v.keys()每个小章节的名字
            for i in v[1].items():
                for d in i[1].items():
                    if d[1]['contentType']=='1':
                        ts_list=[]
                        data['bizId']=d[1]['file_id']
                        ts_url=s.post('https://www.icourse163.org/web/j/resourceRpcBean.getResourceToken.rpc?csrfKey='+csrfkey,data=data)
                        signature=json.loads(ts_url.text)['result']['videoSignDto']['signature']
                        vide_urls=json.loads(s.get('https://vod.study.163.com/eds/api/v1/vod/video?videoId='+d[1]['contentId']+'&signature='+signature+'&clientType=1').text)
                        videos=vide_urls['result']['videos']
                        for url in videos:
                            ts_list.append(url['videoUrl'])
                        ts_dic[d[1]['name']]=ts_list
        return ts_dic
## ts_dic格式
## ts_dic={'视频文件名':[下载地址1,下载地址2,下载地址3],...}  返回的是下载地址 没有进行下载 需要的可以自己写一个用来下载的即可

[Python] 纯文本查看 复制代码
##使用方法:1.复制代码 创建一个类  然后使用其中的方法即可 MOOC.GetPdf()和MOOC.GetTs()返回的是字典  调用接口就可以啦

视频链接获取

视频链接获取

PDF链接获取

PDF链接获取

免费评分

参与人数 14吾爱币 +18 热心值 +13 收起 理由
paguco + 1 + 1 谢谢@Thanks!
queenmly + 1 用心讨论,共获提升!
linden007x + 1 用心讨论,共获提升!
yjn866y + 1 + 1 我很赞同!
elan + 1 + 1 谢谢@Thanks!
gritwang + 1 + 1 谢谢@Thanks!
小夏童学 + 1 + 1 虽然看的挺迷的hh
QRQ + 1 + 1 谢谢@Thanks!
Starry666 + 2 + 1 用心讨论,共获提升!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
扶风绝绝 + 1 + 1 我很赞同!
小鱼干! + 1 鼓励转贴优秀软件安全工具和文档!
小Joe + 1 + 1 我很赞同!
鱼小七七七七七 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 729 发表于 2020-11-24 20:38
Hangjau 发表于 2020-11-24 20:13
老哥贴个链接呢 我也是在论坛下的一个 有点不稳定 有时直接就卡了。

https://www.52pojie.cn/forum.php ... p;highlight=fiddler  当时我大概是下载了这个 我看版本信息是一样的 我没更新过 应该是这个了
 楼主| 729 发表于 2020-11-23 15:39
tianyagd 发表于 2020-11-23 15:32
论坛 也有专门的批量下载工具。

嗯嗯确实有了 也用过 不过好像论坛的那个是要登录的 现在的代码只是用PYTHON实现了一次且不需要登录 批量下载的话懒得写上 不过已经有链接就好下载了
yzqhj 发表于 2020-11-23 14:37
 楼主| 729 发表于 2020-11-23 14:40
yzqhj 发表于 2020-11-23 14:37
楼主可以讲一下分析过程么?

需要分析过程吗?我等等编辑上去吧

免费评分

参与人数 2吾爱币 +4 热心值 +2 收起 理由
xiebaoshan + 2 + 1 热心回复!
yzqhj + 2 + 1 用心讨论,共获提升!

查看全部评分

yzqhj 发表于 2020-11-23 14:43
729 发表于 2020-11-23 14:40
需要分析过程吗?我等等编辑上去吧

嗯嗯,感谢,最近也在学,想学习一下,分析的过程!
lile2960817 发表于 2020-11-23 14:47
收藏  准备学习下
Not小新 发表于 2020-11-23 14:48
收藏学习
鱼小七七七七七 发表于 2020-11-23 14:57
谢谢分享
Lyle61 发表于 2020-11-23 14:59
谢谢分享
Wanggle 发表于 2020-11-23 15:02
谢谢楼主,准备学习下
joshuazm 发表于 2020-11-23 15:05
学习了,谢谢楼主!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-23 17:19

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表