生活随笔
收集整理的這篇文章主要介紹了
对中国大学MOOC课程视频批量下载的探索
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
聲明:請尊重各大高校對慕課內(nèi)容的版權(quán),下載慕課視頻僅為方便自己學(xué)習(xí)使用,請勿肆意傳播或用于商業(yè)用途。一切因?yàn)E用下載所得慕課內(nèi)容所產(chǎn)生的法律問題本人概不負(fù)責(zé)。
中國大學(xué)MOOC是一個公益性質(zhì)的免費(fèi)慕課平臺,由各大高校共享自己的課程內(nèi)容。雖然在這些慕課中有相當(dāng)大一部分是全程念ppt的敷衍之作,但是也不乏一些制作精良、講解用心的精品慕課。然而網(wǎng)易的這個HTML5播放器做得實(shí)在太爛,經(jīng)常會出現(xiàn)兩重聲音,倍速錯亂等各種bug,快進(jìn)快退也很不方便,非常影響觀看體驗(yàn)。IDM自帶的流媒體探測功能雖然可以直接下載播放頁面中的慕課視頻,但是一集一集地下載費(fèi)時費(fèi)力,還需要為每一個下載的文件重命名,于是我萌生了批量下載課程視頻的想法。
首先檢查播放頁面中的HTML5播放器元素,發(fā)現(xiàn)了視頻資源的URL。
但是查看網(wǎng)頁源代碼的時候卻并沒有發(fā)現(xiàn)與HTML5播放器有關(guān)的內(nèi)容,看來這是一個由js即時生成網(wǎng)頁內(nèi)容的動態(tài)網(wǎng)頁。我技術(shù)有限,暫時還不會從動態(tài)網(wǎng)頁上抓取內(nèi)容的操作。而且若要通過獲取視頻播放頁面中視頻的URL來實(shí)現(xiàn)批量下載的話,需要遍歷該課程的所有播放頁面,非常繁瑣。
直接從Web頁面抓取下載鏈接的方法過于繁瑣,于是我將目光投向了手機(jī)客戶端。
為了效率,手機(jī)客戶端與服務(wù)器間一般以簡單易懂的json等方式進(jìn)行通訊,我希望能從手機(jī)客戶端與服務(wù)器的報文中獲取有價值的信息。手機(jī)抓包的方法有很多,出于個人習(xí)慣,這里我選擇了在PC上使用Fiddler 4進(jìn)行抓包。在手機(jī)客戶端登陸賬號,打開對應(yīng)課程,Fiddler中立刻出現(xiàn)了客戶端與服務(wù)器通訊的報文。
經(jīng)過仔細(xì)查看,終于在目的為www.icourse163.org/mob/course/courseLearn/v1的POST方法的response內(nèi)容中發(fā)現(xiàn)了有用信息。
將這一報文復(fù)制出來,發(fā)現(xiàn)這是一份包含該課程的所有信息以及各個視頻的源文件URL的json。將這份json格式化之后,我們可以清晰地看到它的層次結(jié)構(gòu)。
“results”下的”courseDto”包含了當(dāng)前課程的名稱、學(xué)校名稱、簡介等各種信息,”termDto”包含了章節(jié)(”chapters”)課時(”lessons”)課的分節(jié)(”units”)這樣的分層結(jié)構(gòu),在”units”下的”resourceInfo”中,就包含了這節(jié)課的標(biāo)清、高清、超清資源分別對應(yīng)的源文件URL。得到了這份json后,我們就可以根據(jù)其結(jié)構(gòu)編寫代碼來批量下載它們,這里我使用Python。
[python] view plain
copy print?
??import?json??import?os??import?urllib.request??jsonFile=open(’json.txt’).read()??jsonObj=json.loads(jsonFile)??def?Schedule(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)??# -*- 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):#下載進(jìn)度指示'''''a:已經(jīng)下載的數(shù)據(jù)塊b:數(shù)據(jù)塊的大小c:遠(yuǎn)程文件的大小'''per = 100.0 * a * b / cif per > 100 :per = 100print('%.2f%%' % per)
def getMOOCLessons(jsonObj):courseName=jsonObj['results']['courseDto']['name']+" "+jsonObj['results']['courseDto']['schoolName']os.mkdir(courseName)#創(chuàng)建名稱為“課程名+校名”的根目錄chapters=jsonObj['results']['termDto']['chapters']#讀取所有章節(jié)的信息為一個列表for i in range(len(chapters)):#遍歷所有章節(jié)os.mkdir(courseName + '\\' + chapters[i]['name'])#每一個章節(jié)建立一個文件夾print(chapters[i]['name'])lessons=chapters[i]['lessons']#讀取當(dāng)前章節(jié)下所有課時的信息為一個列表for j in range(len(lessons)):#遍歷所有課時units=lessons[j]['units']#讀取當(dāng)前課時下所有小節(jié)的信息為一個列表for k in range(len(units)):#遍歷所有小節(jié)aunit=units[k]if (aunit["contentType"]==1):#判斷該小節(jié)是否為視頻內(nèi)容print("Downloading "+aunit['name'])urllib.request.urlretrieve(aunit["resourceInfo"]["videoHDUrl"], courseName + '\\' + chapters[i]['name']+'\\'+aunit['name']+".mp4", Schedule)#下載文件,這里下載的是高清資源
getMOOCLessons(jsonObj)
執(zhí)行這段Python程序即可自動批量下載慕課視頻,因?yàn)橄螺d耗時很長,我在這里將它丟到了樹莓派上執(zhí)行,最終按照預(yù)想生成了對應(yīng)的目錄結(jié)構(gòu)并成功下載課程全部視頻。
這里只是簡單地實(shí)現(xiàn)了功能,如果想提高效率可以進(jìn)一步將程序改為多線程執(zhí)行。
http://blog.csdn.net/wxyedward/article/details/79080246
總結(jié)
以上是生活随笔為你收集整理的对中国大学MOOC课程视频批量下载的探索的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。