最近需要频繁的在datacamp上完成课程作业,而datacamp的视频加载特别慢,如果能够将视频打包下载就好了。因此尝试在之前写的go爬虫的基础上增加下载datacamp视频以及字幕的功能。
1.网站分析
1.1 单个视频
单个视频的播放地址示例为
https://projector.datacamp.com/?auto_play=play&projector_key=course_2300_39936ca75b4f429f2edd5a6f5623a0f0&playback_rate=1&quality=auto
这个地址进行get请求可以获得mp4格式视频的地址以及vtt格式字幕的地址,因此每一个视频可以通过该网址进行下载,而拼接出该网址的关键参数为projector_key,接下来的目标就是获得这个参数。
1.2 课程列表
课程页面为
https://learn.datacamp.com/courses/data-visualization-with-ggplot2-2
转换成如下地址
https://campus.datacamp.com/courses/data-visualization-with-ggplot2-2/
发送get请求,在返回的页面中可以获得一个巨大的转义后的json数组
VideoExercise","^1","Stats and Geoms","aggregate_xp",50,"^18",1,"url","https://campus.datacamp.com/courses/data-visualization-with-ggplot2-2/chapter-1-statistics?ex=1
使用正则表达式将其提取出可以获得视频的课程地址,在此地址可以获得视频的projector_key
,再拼接出单个视频的播放地址,返回其mp4视频地址以及字幕地址即可。
2. 实现
起始地址示例为
https://campus.datacamp.com/courses/data-visualization-with-ggplot2-2
2.1 获取视频的课程地址
返回视频课程地址的列表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
func GetDCName(url string)string {
return utils.MatchAll(url,`courses/(.*)`)[0][1]
}
//从起始地址得到带视频章节的下载页面,返回视频列表
func GetDCStartURLs(starturl string) ([]string) {
//从起始地址中提取课程名称
courseName := GetDCName(starturl)
//拼接出正确的地址
url := "https://campus.datacamp.com/courses/"+courseName
data:=utils.HttpGet(url)
//fmt.Print(data)
var list []string
content := utils.MatchAll(data,`VideoExercise.*?(https://campus.datacamp.com/courses/.*?)"`)
for _,item := range(content){
list = append(list, item[1])
}
return list
}
|
2.2 返回视频和字幕的下载地址
对于每一个课程地址,用正则表达式提取出projector_key
1
|
projector_key","course_775_8ef45bdbcab9689af067e6898d1ced76","
|
拼接出播放地址,发送get请求,返回结果中包含文件信息的内容如下:
{"id":16063,"key":"course_775_8bd0470dcdd674c3f9858a6645528303","video_raw_link":null,"video_mp4_link":"//videos.datacamp.com/transcoded_mp4/775_ggplot2_2/v2/ch1_1.mp4","video_hls_link":"//videos.datacamp.com/transcoded/775_ggplot2_2/v2/hls-ch1_1.master.m3u8","audio_link":"https://s3.amazonaws.com/assets.datacamp.com/production/course_775/audio/chapter1_exercise_3c84aedc95.mp3","slides_link":null,"script_link":"https://assets.datacamp.com/production/course_775/scripts/chapter1_exercise_3c84aedc95.md","subtitle_vtt_link":"https://s3.amazonaws.com/assets.datacamp.com/production/course_775/subtitles/course_775_8bd0470dcdd674c3f9858a6645528303.vtt","transcript_timings":null,"slide_deck_id":null,"created_at":"2018-01-26T20:56:55.000Z","updated_at":"2018-01-26T20:56:55.000Z","deleted_at":null,"thumbnail_link":null,"render_dynamically":0,"dynamic_slide_deck_id":null,"is_projector_video":0,"active_mp4_conversion_id":null,"active_pdf_conversion_id":null}
使用正则表达式提取出这两个地址
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//提取单个视频的projector_key
func GetPK(url string)(string){
data:=utils.HttpGet(url)
PK := utils.MatchAll(data,`projector_key.*?(course_.*?)"`)[0][1]
return PK
}
//根据project key 返回视频和字幕的下载地址
func GetDCVideo(PK string)(string,string){
url := "https://projector.datacamp.com/?auto_play=play&projector_key="+PK
data:=utils.HttpGet(url)
videoUrl:= "https:"+utils.MatchAll(data,`video_mp4_link.*?(//videos.datacamp.com/transcoded_mp4/.*?mp4)`)[0][1]
subtitleUrl := utils.MatchAll(data,`subtitle_vtt_link.*?(https.*?vtt)`)[0][1]
return videoUrl,subtitleUrl
}
|
2.3 获取课件的下载地址
课件的下载地址列表可以在提取视频课程列表的时候一并完成,修改后的程序如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//从起始地址得到带视频章节的下载页面,返回视频列表和pdf课件列表
func GetDCStartURLs(starturl string) ([]string,[]string) {
//从起始地址中提取课程名称
courseName := GetDCName(starturl)
//拼接出正确的地址
url := "https://campus.datacamp.com/courses/"+courseName
data:=utils.HttpGet(url)
//fmt.Print(data)
var urlList []string
var pdfList []string
content := utils.MatchAll(data,`VideoExercise.*?(https://campus.datacamp.com/courses/.*?)"`)
ppts := utils.MatchAll(data,`slides_link.*?(https.*?pdf)`)
//fmt.Print(ppts)
for _,item := range(content){
urlList = append(urlList, item[1])
}
//pdfList 有重复的
for _,item := range(ppts){
pdfList = append(pdfList, item[1])
}
return urlList,pdfList
}
|
3. 实际运行
由于视频以及课件下载速度比较慢,因此将其下载地址整理到一个文档中,并自动生成批量处理的重命名文件(windows下,linux将ren
改为move
即可)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
//返回待下载的视频文件列表和字幕文件列表
func ExtractDCVideo(url string)([]utils.File,[]utils.File){
//需要下载的文件集合
var videos []utils.File
var subtitles []utils.File
urlList,pdfList := GetDCStartURLs(url)
//放置下载信息的列表
var downloadList []string
var renameList []string
//fmt.Println(urlList)
//对于每一个视频
for _,item := range(urlList){
PK := GetPK(item)
//添加下载链接
videoUrl,subtitleUrl := GetDCVideo(PK)
downloadList = append(downloadList,videoUrl )
downloadList = append(downloadList,subtitleUrl )
fileName := utils.MatchAll(videoUrl,`.*/(.*?).mp4`)[0][1]
subtitleName := utils.MatchAll(subtitleUrl,`.*/(.*?.vtt)`)[0][1]
//添加重命名命令
renameCM := "ren "+subtitleName+" "+fileName+".vtt"
fmt.Println(renameCM)
renameList = append(renameList,renameCM)
videos = append(videos, utils.File{videoUrl,fileName+".mp4"})
subtitles = append(subtitles, utils.File{subtitleUrl,fileName+".vtt"})
}
utils.WriteFile("downloadList.txt",downloadList)
utils.WriteFile("rename.bat",renameList)
utils.WriteFile("pdflist.txt",pdfList)
return videos,subtitles
}
|
运行一次生成3个文件
1
|
go run main.go https://learn.datacamp.com/courses/data-visualization-with-ggplot2-part-3
|
分别为
downloadList.txt
存储视频和字幕地址
rename.bat
重命名的批量处理文件
pdflist.txt
课件文件
4.总结
该项目的地址为:https://github.com/webscrapingproject/icourse-downloader , 欢迎讨一起讨论!
PS:真的巨久没有更新博客了,接下来希望能够学习一些有趣的机器学习项目(总是在说想做NLP什么的,一直没有动手那就等于没有空想)。自己也要抓紧这时间学习,掌握更多的技术。