极客学院职业路径图课程视频下载-爬虫
一、序言
最近看了极客学院的视频教程,相当不错,渴望把视频下载到本地。手动下载耗时耗力,因而决定研究一番,写一程序自动下载,终于小有成果!有图为证:
二、技术难点
既然要实现自动下载,免不了要爬取极客学院的页面获取视频地址。经尝试,可以发现大部分视频观看是需要登录,并且是会员。于是所要解决的要点有:
1、拥有会员
2、模拟登录
3、解析html
4、继续下载(可能出现异常情况下)
三、实现
(1)、要获取极客学院会员相当简单(如果已经是会员用户,可跳过此步骤),利用邀请好友获取30天体验,如下图:(30天足够把所有的视频下载完毕)
(2)、会员问题解决了,最大的难点就是模拟登录了。细心的人就会发现,极客学院提供了一个ajax方式登录的接口!如下图:
当我们点击登录的时候,会发起一个ajax请求,通过抓包工具,我们可以获取到登录地址:http://passport.jikexueyuan.com/submit/login?is_ajax=1,验证码地址:http://passport.jikexueyuan.com/sso/verify
“万事俱备只欠东风”,地址都知道了,还怕登录不了么?如下是本人最终实现登录效果:
1 /// <summary> 2 /// 获取验证码 3 /// </summary> 4 void GetVerifyCode() 5 { 6 VerifyCode.Source = null; 7 8 // 1. 先请求登录地址,获取到当前用户的会话cookie 9 HttpResponseParameter responseParameter = HttpProvider.Excute(new HttpRequestParameter 10 { 11 IsPost = false, 12 Url = "http://passport.jikexueyuan.com/sso/login" 13 }); 14 SessionCookie = responseParameter.Cookie; 15 16 // 2.带上会话cookie请求验证码图片(保证是当前用户) 17 HttpProvider.Excute(new HttpRequestParameter 18 { 19 Url = string.Format("http://passport.jikexueyuan.com/sso/verify?t={0}", DateTime.Now.ToString("yyyyMMddHHmmsss")), 20 Cookie = SessionCookie, 21 ResponseEnum = HttpResponseEnum.Stream, 22 StreamAction = x => 23 { 24 MemoryStream ms = new MemoryStream(); 25 byte[] buffer = new byte[1024]; 26 while (true) 27 { 28 int sz = x.Read(buffer, 0, buffer.Length); 29 if (sz == 0) break; 30 ms.Write(buffer, 0, sz); 31 } 32 ms.Position = 0; 33 34 BitmapImage bmp = new BitmapImage(); 35 bmp.BeginInit(); 36 bmp.StreamSource = new MemoryStream(ms.ToArray()); 37 bmp.EndInit(); 38 39 VerifyCode.Source = bmp; 40 41 ms.Close(); 42 } 43 }); 44 }
获取验证码
1 /// <summary> 2 /// 登录方法 3 /// </summary> 4 /// <param name="userName">账号</param> 5 /// <param name="userPwd">密码</param> 6 /// <param name="verifyCode">验证码</param> 7 void LoginDo(string userName, string userPwd, string verifyCode) 8 { 9 // 1.登录 10 IDictionary<string, string> postData = new Dictionary<string, string>(); 11 postData.Add("referer", HttpUtility.UrlEncode("http://www.jikexueyuan.com/")); 12 postData.Add("uname", userName); 13 postData.Add("password", userPwd); 14 postData.Add("is_ajax", "1"); 15 postData.Add("verify", verifyCode); 16 HttpResponseParameter responseParameter = HttpProvider.Excute(new HttpRequestParameter 17 { 18 Url = "http://passport.jikexueyuan.com/submit/login?is_ajax=1", 19 IsPost = true, 20 Parameters = postData, 21 Cookie = SessionCookie 22 }); 23 24 LoginResultEntity loginResult = responseParameter.Body.DeserializeObject<LoginResultEntity>(); 25 if (loginResult.status == 1) 26 { 27 // 2.登录成功,保存cookie 28 CookieStoreInstance.CurrentCookie = responseParameter.Cookie; 29 } 30 31 //MessageBox.Show(string.Format("body={0},cookie={1}", Unicode2String(responseParameter.Body), 32 // responseParameter.Cookie.CookieString)); 33 }
登录代码
流程说明:先访问极客学院任意页面(这里已首页为例,),获取到当前的用户访问的会话cookie(这里还是未登录的cookie), 然后拉取验证码,封装数据发起登录请求。把登录成功后的cooki保存在本地文件或全局变量中(本例使用),以备下载视频使用。
(3)登录成功后,接下来就是获取视频下载地址。这里以http://www.jikexueyuan.com/course/360.html这个地址为例。访问这个地址如下图
查看源代码,我们会发现一段惊奇的代码:<source src=”http://cv4.jikexueyuan.com/ae892b3b4a8c63fa579af4d2c6f6bb03/201512151558/csharp/course_360/01/video/c360b_01_h264_sd_960_540.mp4” type=”video/mp4″ />,其中src地址就是我们所需的视频地址(必须登录才有这段代码)。因此应该先解析此页面,获取课时列表的链接。然后一个一个遍历发起Http请求(注意带cookie)获取视频地址,然后下载保存到本地。
1 public List<LessonEntity> GetLessonEntities(string url, HttpCookieType sessionCookie) 2 { 3 // 请求课时列表,解析html源码,并提取课时 信息和链接 4 HttpResponseParameter responseParameter = HttpProvider.Excute(new HttpRequestParameter() 5 { 6 IsPost = false, 7 Url = url, 8 Encoding = Encoding.UTF8, 9 Cookie = sessionCookie 10 }); 11 12 List<LessonEntity> results = new List<LessonEntity>(); 13 14 HtmlDocument htmlDocument = new HtmlDocument(); 15 htmlDocument.LoadHtml(responseParameter.Body); 16 HtmlNode rootNode = htmlDocument.DocumentNode; 17 HtmlNodeCollection lessonNodes = rootNode.SelectNodes("//div[@id=\"pager\"]/div[3]/div[2]/div[2]/ul/li"); 18 foreach (HtmlNode lessonNode in lessonNodes) 19 { 20 HtmlNode aNode = lessonNode.SelectSingleNode("div[1]/h2[1]/a[1]"); 21 if (aNode != null) 22 { 23 results.Add(new LessonEntity 24 { 25 Title = aNode.InnerText.Trim(), 26 Href = aNode.GetAttributeValue("href", string.Empty) 27 }); 28 } 29 } 30 31 return results; 32 }
获取课时列表
public string GetVideoUrl(string url, HttpCookieType sessionCookie) { HttpResponseParameter responseParameter = HttpProvider.Excute(new HttpRequestParameter { Url = url, Cookie = sessionCookie }); // 正则提前视频文件 地址 string result = Regex.Match(responseParameter.Body, "<source.*src=\"(.+?\").*/>").Groups[1].Value.Replace("\"", string.Empty); sessionCookie = responseParameter.Cookie; return result; }
获取视频地址
public void DownloadVideo(string filePath, string url, HttpCookieType sessionCookie, Action action = null) { string folder = Path.GetDirectoryName(filePath); if (!string.IsNullOrEmpty(folder) && !Directory.Exists(folder)) { // 如果目录文件夹不存在, 则创建 Directory.CreateDirectory(folder); } if (action != null) { action(); } HttpProvider.Excute(new HttpRequestParameter { Url = url, ResponseEnum = HttpResponseEnum.Stream, Cookie = sessionCookie, StreamAction = x => { NetExtensions.WriteFile(filePath, x); } }); //WebClient webClient = new WebClient(); //webClient.DownloadFile(new Uri(url, UriKind.RelativeOrAbsolute), filePath); }
下载视频
1 public void DownloadCode(string filePath, string courseId, HttpCookieType sessionCookie) 2 { 3 if (File.Exists(filePath)) return; 4 5 HttpResponseParameter responseParameter = HttpProvider.Excute(new HttpRequestParameter 6 { 7 Url = string.Format("http://www.jikexueyuan.com/course/downloadRes?course_id={0}", courseId), 8 Cookie = sessionCookie 9 }); 10 CodeDownloadResultEntity result = responseParameter.Body.DeserializeObject<CodeDownloadResultEntity>(); 11 if (result.code == 200) 12 { 13 string folder = Path.GetDirectoryName(filePath); 14 if (!string.IsNullOrEmpty(folder) && !Directory.Exists(folder)) 15 { 16 // 如果目录文件夹不存在, 则创建 17 Directory.CreateDirectory(folder); 18 } 19 20 WebClient webClient = new WebClient(); 21 webClient.DownloadFile(new Uri(result.data.url, UriKind.RelativeOrAbsolute), filePath); 22 } 23 }
下载课件和源码
(4)、至此视频下载功能已完成。那么我们要批量下载极客学院【职业路径图课程视频】就相当简单了(http://ke.jikexueyuan.com/zhiye/),一步一步解析页面,获取到视频播放页地址,下载视频(解析页面主要用到正则表达式和HtmlAgilityPack框架)。
(5)如此,极客学院职业路径图课程就可以尽收囊中。
四、源码下载
“苟富贵勿相忘”,如果这篇文章是你认为好的,无论你是一直潜水,请点个赞好吗?