您的位置:首页 > 其它

对中国大学MOOC课程视频批量下载的探索

2018-01-16 23:29 274 查看
声明:请尊重各大高校对慕课内容的版权,下载慕课视频仅为方便自己学习使用,请勿肆意传播或用于商业用途。一切因滥用下载所得慕课内容所产生的法律问题本人概不负责。

中国大学MOOC是一个公益性质的免费慕课平台,由各大高校共享自己的课程内容。虽然在这些慕课中有相当大一部分是全程念ppt的敷衍之作,但是也不乏一些制作精良、讲解用心的精品慕课。然而网易的这个HTML5播放器做得实在太烂,经常会出现两重声音,倍速错乱等各种bug,快进快退也很不方便,非常影响观看体验。IDM自带的流媒体探测功能虽然可以直接下载播放页面中的慕课视频,但是一集一集地下载费时费力,还需要为每一个下载的文件重命名,于是我萌生了批量下载课程视频的想法。

首先检查播放页面中的HTML5播放器元素,发现了视频资源的URL。



但是查看网页源代码的时候却并没有发现与HTML5播放器有关的内容,看来这是一个由js即时生成网页内容的动态网页。我技术有限,暂时还不会从动态网页上抓取内容的操作。而且若要通过获取视频播放页面中视频的URL来实现批量下载的话,需要遍历该课程的所有播放页面,非常繁琐。

直接从Web页面抓取下载链接的方法过于繁琐,于是我将目光投向了手机客户端。



为了效率,手机客户端与服务器间一般以简单易懂的json等方式进行通讯,我希望能从手机客户端与服务器的报文中获取有价值的信息。手机抓包的方法有很多,出于个人习惯,这里我选择了在PC上使用Fiddler 4进行抓包。在手机客户端登陆账号,打开对应课程,Fiddler中立刻出现了客户端与服务器通讯的报文。



经过仔细查看,终于在目的为www.icourse163.org/mob/course/courseLearn/v1的POST方法的response内容中发现了有用信息。

将这一报文复制出来,发现这是一份包含该课程的所有信息以及各个视频的源文件URL的json。将这份json格式化之后,我们可以清晰地看到它的层次结构。



"results"下的"courseDto"包含了当前课程的名称、学校名称、简介等各种信息,"termDto"包含了章节("chapters")课时("lessons")课的分节("units")这样的分层结构,在"units"下的"resourceInfo"中,就包含了这节课的标清、高清、超清资源分别对应的源文件URL。得到了这份json后,我们就可以根据其结构编写代码来批量下载它们,这里我使用Python。

# -*- coding: utf-8 -*-
import json
import os
import urllib.request
jsonFile=open('json.txt').read()#事先将抓包所得的json保存为同目录下的文本文件
jsonObj=json.loads(jsonFile)
def Schedule(a,b,c):#下载进度指示
'''''
a:已经下载的数据块
b:数据块的大小
c:远程文件的大小
'''
per = 100.0 * a * b / c
if per > 100 :
per = 100
print('%.2f%%' % per)
def getMOOCLessons(jsonObj):
courseName=jsonObj['results']['courseDto']['name']+" "+jsonObj['results']['courseDto']['schoolName']
os.mkdir(courseName)#创建名称为“课程名+校名”的根目录
chapters=jsonObj['results']['termDto']['chapters']#读取所有章节的信息为一个列表
for i in range(len(chapters)):#遍历所有章节
os.mkdir(courseName + '\\' + chapters[i]['name'])#每一个章节建立一个文件夹
print(chapters[i]['name'])
lessons=chapters[i]['lessons']#读取当前章节下所有课时的信息为一个列表
for j in range(len(lessons)):#遍历所有课时
units=lessons[j]['units']#读取当前课时下所有小节的信息为一个列表
for k in range(len(units)):#遍历所有小节
aunit=units[k]
if (aunit["contentType"]==1):#判断该小节是否为视频内容
print("Downloading "+aunit['name'])
urllib.request.urlretrieve(aunit["resourceInfo"]["videoHDUrl"], courseName + '\\' + chapters[i]['name']+'\\'+aunit['name']+".mp4", Schedule)#下载文件,这里下载的是高清资源
getMOOCLessons(jsonObj)


执行这段Python程序即可自动批量下载慕课视频,因为下载耗时很长,我在这里将它丢到了树莓派上执行,最终按照预想生成了对应的目录结构并成功下载课程全部视频。



这里只是简单地实现了功能,如果想提高效率可以进一步将程序改为多线程执行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: