//下载漫画 public bool Download() { //开始下载 delegates.TipText(new ParaTipText(this.Info, "正在分析漫画地址")); try { //取得Url源文件 string src = Network.GetHtmlSource(Info.Url, Encoding.UTF8, Info.Proxy); //要下载的Url列表(页面) List <string> subUrls = new List <string>(); //漫画id int comicId; //是否为漫画的介绍页面 bool isIntroPage = !Regex.IsMatch(Info.Url, @"/HTML/\w+/\w+", RegexOptions.IgnoreCase); #region 确定是整部漫画还是单独一话 //如果为整部漫画 if (isIntroPage) { //取得所有漫画的列表 Regex rAllComics = new Regex(@"<li><a href=""(?<page>(http://\w+\.sfacg\.com/AllComic/)?.+?)"" target=""_blank"">(?<title>.+?)</a>"); MatchCollection mcAllComics = rAllComics.Matches(src); //新建(url-标题)字典 var dict = new Dictionary <string, string>(); foreach (Match item in mcAllComics) { string comicPage = item.Groups["page"].Value; if (comicPage.StartsWith("/")) { comicPage = "http://comic.sfacg.com" + comicPage; } string comicTitle = item.Groups["title"].Value; if (Regex.IsMatch(comicTitle, @"(?<=<(\w+) .*?>).+?(?=</\1>)")) { comicTitle = Regex.Match(comicTitle, @"(?<=<(\w+) .*?>).+?(?=</\1>)").Value; } dict.Add(comicPage, comicTitle); } //选择下载哪部漫画 var selected = ToolForm.CreateMultiSelectForm(dict, Info.AutoAnswer, "sfacgcomic"); //将地址填充到下载列表中 subUrls.AddRange(selected); //如果用户没有选择任何章节 if (subUrls.Count == 0) { return(false); } //取得漫画标题 string title = Regex.Match(src, @"(?<=<title>).+?(?=,)").Value; //过滤标题中的非法字符 title = Tools.InvalidCharacterFilter(title, ""); Info.Title = title; //获取漫画ID comicId = int.Parse(Regex.Match(src, @"(?<=var comicCounterID = )\d+", RegexOptions.IgnoreCase).Value); } else //如果不是整部漫画则添加此单话url { subUrls.Add(Info.Url); //取得漫画标题 //取得源代码并分析 string pSrc = Network.GetHtmlSource(Info.Url, Encoding.UTF8, Info.Proxy); //取得漫画标题 Regex rTitle = new Regex(@"> > <a href=""http://comic.sfacg.com/HTML/.+>(?<title>.+?)</a>"); Match mTitle = rTitle.Match(pSrc); string title = mTitle.Groups["title"].Value; //过滤标题中的非法字符 title = Tools.InvalidCharacterFilter(title, ""); Info.Title = title; //获取漫画ID comicId = int.Parse(Regex.Match(pSrc, @"(?<=var c = )\d+", RegexOptions.IgnoreCase).Value); } //end if #endregion #region 载漫画 //建立文件夹 string mainDir = Info.SaveDirectory + (Info.SaveDirectory.ToString().EndsWith(@"\") ? "" : @"\") + Info.Title; //确定漫画共有几个段落 Info.PartCount = subUrls.Count; //分段落下载 for (int i = 0; i < Info.PartCount; i++) { Info.CurrentPart = i + 1; //提示更换新Part delegates.NewPart(new ParaNewPart(this.Info, i + 1)); //地址数组 Dictionary <string, string> files = new Dictionary <string, string>(); //分析源代码,取得下载地址 WebClient wc = new WebClient(); if (Info.Proxy != null) { wc.Proxy = Info.Proxy; } //取得源代码 byte[] buff = wc.DownloadData(subUrls[i]); string cookie = wc.ResponseHeaders.Get("Set-Cookie"); string source = Encoding.UTF8.GetString(buff); //取得标题 Regex rTitle = new Regex(@"> > (?<title>\S+?)</div>"); Match mTitle = rTitle.Match(source); string subTitle = mTitle.Groups["title"].Value; //过滤子标题中的非法字符 subTitle = Tools.InvalidCharacterFilter(subTitle, ""); //合并本地路径(文件夹) string subDir = mainDir + @"\" + subTitle; //创建文件夹 Directory.CreateDirectory(subDir); #region 取得js文件 //取得js文件路径 string urljs = subUrls[i]; //分析漫画id Regex rjs = new Regex(@"(?<server>http://\w+\.sfacg\.com/)HTML/\w+/(?<id>.+)"); Match mjs = rjs.Match(urljs); string jsserver = mjs.Groups["server"].Value; string jsid = mjs.Groups["id"].Value.TrimEnd('/'); urljs = jsserver + "Utility/" + comicId + "/" + jsid + ".js"; #endregion //取得JS文件内容 string jscontent = Network.GetHtmlSource(urljs, Encoding.UTF8); //添加到url数组 Regex rFiles = new Regex(@"picAy\[(?<no>\d+)\] = ""(?<file>.+?(?<ext>\w{3}))"""); MatchCollection mFiles = rFiles.Matches(jscontent); //添加url到数组 foreach (Match item in mFiles) { //将 url - 本地文件 添加到字典中 files.Add("http://comic.sfacg.com/" + item.Groups["file"].Value, Path.Combine(subDir, item.Groups["no"].Value + "." + item.Groups["ext"].Value)); } //设置下载长度 currentParameter.TotalLength = files.Count; currentParameter.DoneBytes = 0; //下载文件 foreach (string key in files.Keys) { if (currentParameter.IsStop) { return(false); } try { wc.Headers.Add("Referer", subUrls[i]); wc.Headers.Add("Cookie", cookie); byte[] content = wc.DownloadData(key); File.WriteAllBytes(files[key], content); } catch { } //end try currentParameter.DoneBytes += 1; } // end foreach } //end for #endregion } //end try catch (Exception ex) //出现错误即下载失败 { throw ex; } //end try //下载成功完成 currentParameter.DoneBytes = currentParameter.TotalLength; return(true); } //end DownloadVideo
/// <summary> /// 下载视频 /// </summary> /// <returns></returns> public override bool Download() { //开始下载 delegates.TipText(new ParaTipText(this.Info, "正在分析视频地址")); //修正井号 Info.Url = Info.Url.TrimEnd('#'); //修正简写URL if (Regex.Match(Info.Url, @"^ac\d+$").Success) { Info.Url = "http://www.acfun.tv/v/" + Info.Url; } else if (!Info.Url.StartsWith("http://", StringComparison.CurrentCultureIgnoreCase)) { Info.Url = "http://" + Info.Url; } //修正URL为 http://www.acfun.tv/v/ac12345_67 形式 Info.Url = Info.Url.Replace(".html", "").Replace("/index", ""); if (!Info.Url.Contains("_")) { Info.Url += "_1"; } //取得AC号和子编号 Match mAcNumber = Regex.Match(Info.Url, @"(?<ac>ac\d+)_(?<sub>\d+)"); m_acNumber = mAcNumber.Groups["ac"].Value; m_acSubNumber = mAcNumber.Groups["sub"].Value; //设置自定义文件名 m_customFileName = AcFunPlugin.DefaultFileNameFormat; if (Info.BasePlugin.Configuration.ContainsKey("CustomFileName")) { m_customFileName = Info.BasePlugin.Configuration["CustomFileName"]; } //是否通过【自动应答】禁用对话框 bool disableDialog = false; disableDialog = AutoAnswer.IsInAutoAnswers(Info.AutoAnswer, "acfun", "auto"); //当前播放器地址 Settings["PlayerUrl"] = @"http://static.acfun.tv/player/ssl/ACFlashPlayerN0102.swf"; //取得网页源文件 string src = Network.GetHtmlSource(Info.Url, Encoding.UTF8, Info.Proxy); var relatedVideoList = new Dictionary <string, string>(); TipText("正在获取视频详细信息"); var videoIdCollection = Regex.Matches(src, @"<a data-vid=""(?<vid>\d+)"" data-from=""(?<from>\w+)""(?: data-did=""(?<did>\w*?)"")? data-sid=""(?<sid>\w+)"" href=""(?<href>.+?)"" title=""(?<title>.+?)"".+?>(?<content>.+?)</a>", RegexOptions.IgnoreCase); foreach (Match mVideoId in videoIdCollection) { //所有子标题 if (mVideoId.Groups["content"].Value.Contains("<i")) //当前标题 { m_currentPartTitle = Regex.Replace(mVideoId.Groups["content"].Value, @"<i.+?i>", "", RegexOptions.IgnoreCase); m_currentPartVideoId = mVideoId.Groups["vid"].Value; } else //其他标题 { relatedVideoList.Add("http://www.acfun.tv" + mVideoId.Groups["href"].Value, mVideoId.Groups["content"].Value); } } //取得视频标题 var videoTitleMatchResult = Regex.Match(src, @"(?<=system\.title = \$\.parseSafe\(')(.+?)(?='\))", RegexOptions.IgnoreCase); if (!videoTitleMatchResult.Success) { videoTitleMatchResult = Regex.Match(src, @"(?<=<title>).+?(?=</title>)", RegexOptions.IgnoreCase); } m_videoTitle = videoTitleMatchResult.Value; m_currentPartTitle = string.IsNullOrEmpty(m_currentPartTitle) ? m_videoTitle : m_currentPartTitle; m_currentPartTitle = m_currentPartTitle.Replace(" - AcFun弹幕视频网 - 中国宅文化基地", ""); //取得当前视频完整标题 Info.Title = m_videoTitle + " - " + m_currentPartTitle; m_videoTitle = Tools.InvalidCharacterFilter(m_videoTitle, ""); m_currentPartTitle = Tools.InvalidCharacterFilter(m_currentPartTitle, ""); //解析关联项需要同时满足的条件: //1.这个任务不是被其他任务所添加的 //2.用户设置了“解析关联项” TipText("正在选择关联视频"); if (!Info.IsBeAdded && Info.ParseRelated && relatedVideoList.Count > 0) { //用户选择任务 var ba = new Collection <string>(); if (!disableDialog) { ba = ToolForm.CreateMultiSelectForm(relatedVideoList, Info.AutoAnswer, "acfun"); } //根据用户选择新建任务 foreach (string u in ba) { //新建任务 delegates.NewTask(new ParaNewTask(Info.BasePlugin, u, this.Info)); } } //视频地址数组 //清空地址 Info.FilePath.Clear(); Info.SubFilePath.Clear(); //下载弹幕 DownloadSubtitle(m_currentPartVideoId); TipText("正在解析视频源地址"); //解析器的解析结果 ParseResult pr = null; //如果允许下载视频 if ((Info.DownloadTypes & DownloadType.Video) != 0) { var parser = new AcfunInterfaceParser(); pr = parser.Parse(new ParseRequest { Id = m_currentPartVideoId, Proxy = Info.Proxy, AutoAnswers = Info.AutoAnswer }); //视频地址列表 var videos = pr.ToArray(); //支持导出列表 if (videos != null) { var sb = new StringBuilder(); foreach (string item in videos) { sb.Append(item); sb.Append("|"); } Settings["ExportUrl"] = sb.ToString(); } //下载视频 TipText("正在开始下载视频文件"); //确定视频共有几个段落 Info.PartCount = videos.Length; //------------分段落下载------------ for (int i = 0; i < Info.PartCount; i++) { Info.CurrentPart = i + 1; //取得文件后缀名 string ext = Tools.GetExtension(videos[i]); if (string.IsNullOrEmpty(ext)) { if (string.IsNullOrEmpty(Path.GetExtension(videos[i]))) { ext = ".flv"; } else { ext = Path.GetExtension(videos[i]); } } if (ext == ".hlv") { ext = ".flv"; } //设置文件名 var renamehelper = new CustomFileNameHelper(); string filename = renamehelper.CombineFileName(m_customFileName, m_videoTitle, m_currentPartTitle, Info.PartCount == 1 ? "" : Info.CurrentPart.ToString(), ext.Replace(".", ""), m_acNumber, m_acSubNumber); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); //添加文件名到文件列表中 Info.FilePath.Add(filename); //生成父文件夹 if (!Directory.Exists(Path.GetDirectoryName(filename))) { Directory.CreateDirectory(Path.GetDirectoryName(filename)); } //设置当前DownloadParameter currentParameter = new DownloadParameter() { //文件名 FilePath = filename, //文件URL Url = videos[i], //代理服务器 Proxy = Info.Proxy, //提取缓存 ExtractCache = Info.ExtractCache, ExtractCachePattern = "fla*.tmp" }; //下载文件 bool success = false; //提示更换新Part delegates.NewPart(new ParaNewPart(this.Info, i + 1)); //下载视频 try { success = Network.DownloadFile(currentParameter, this.Info); if (!success) //未出现错误即用户手动停止 { return(false); } } catch //下载文件时出现错误 { //如果此任务由一个视频组成,则报错(下载失败) if (Info.PartCount == 1) { throw; } else //否则继续下载,设置“部分失败”状态 { Info.PartialFinished = true; Info.PartialFinishedDetail += "\r\n文件: " + currentParameter.Url + " 下载失败"; } } } //end for } //end 判断是否下载视频 //如果插件设置中没有GenerateAcPlay项,或此项设置为true则生成.acplay快捷方式 if (!Info.BasePlugin.Configuration.ContainsKey("GenerateAcPlay") || Info.BasePlugin.Configuration["GenerateAcPlay"] == "true") { //生成AcPlay文件 string acplay = GenerateAcplayConfig(pr); //支持AcPlay直接播放 Settings["AcPlay"] = acplay; } //生成视频自动合并参数 if (Info.FilePath.Count > 1 && !Info.PartialFinished) { Info.Settings.Remove("VideoCombine"); var arg = new StringBuilder(); foreach (var item in Info.FilePath) { arg.Append(item); arg.Append("|"); } var renamehelper = new CustomFileNameHelper(); string filename = renamehelper.CombineFileName(m_customFileName, m_videoTitle, m_currentPartTitle, "", "mp4", m_acNumber, m_acSubNumber); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); arg.Append(filename); Info.Settings["VideoCombine"] = arg.ToString(); } //下载成功完成 return(true); }
//下载视频 public bool Download() { //开始下载 delegates.TipText(new ParaTipText(this.Info, "正在分析视频地址")); //修正井号 Info.Url = Info.Url.TrimEnd('#'); //修正旧版URL Info.Url = Info.Url.Replace("bilibili.us", "bilibili.tv"); //修正简写URL if (Regex.Match(Info.Url, @"^av\d{2,6}$").Success) { Info.Url = "http://www.bilibili.tv/video/" + Info.Url + "/"; } //修正index_1.html if (!Info.Url.EndsWith(".html")) { if (Info.Url.EndsWith("/")) { Info.Url += "index_1.html"; } else { Info.Url += "/index_1.html"; } } string url = Info.Url; //取得子页面文件名(例如"/video/av12345/index_123.html") string suburl = Regex.Match(Info.Url, @"bilibili\.tv(?<part>/video/av\d+/index_\d+\.html)").Groups["part"].Value; //是否通过【自动应答】禁用对话框 bool disableDialog = false; if (Info.AutoAnswer != null) { foreach (var item in Info.AutoAnswer) { if (item.Prefix == "bilibili") { if (item.Identify == "auto") { disableDialog = true; } break; } } } //视频地址数组 string[] videos = null; try { //取得网页源文件 string src = Network.GetHtmlSource(url, Encoding.UTF8, Info.Proxy); //type值 string type = ""; #region 登录并重新获取网页源文件 //检查是否需要登录 if (src.Contains("您无权访问本页面")) //需要登录 { CookieContainer cookies = new CookieContainer(); //登录Bilibili UserLoginInfo user; //检查插件配置 try { user = new UserLoginInfo(); user.Username = Encoding.UTF8.GetString(Convert.FromBase64String(Info.Settings["user"])); user.Password = Encoding.UTF8.GetString(Convert.FromBase64String(Info.Settings["password"])); if (string.IsNullOrEmpty(user.Username) || string.IsNullOrEmpty(user.Password)) { throw new Exception(); } } catch { user = ToolForm.CreateLoginForm("https://secure.bilibili.tv/member/index_do.php?fmdo=user&dopost=regnew"); Info.Settings["user"] = Convert.ToBase64String(Encoding.UTF8.GetBytes(user.Username)); Info.Settings["password"] = Convert.ToBase64String(Encoding.UTF8.GetBytes(user.Password)); } //Post的数据 string postdata = "fmdo=login&dopost=login&refurl=http%%3A%%2F%%2Fbilibili.tv%%2F&keeptime=604800&userid=" + user.Username + "&pwd=" + user.Password + "&keeptime=604800"; byte[] data = Encoding.UTF8.GetBytes(postdata); //生成请求 HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("https://secure.bilibili.tv/member/index_do.php"); req.Method = "POST"; req.Referer = "https://secure.bilibili.tv/login.php"; req.ContentType = "application/x-www-form-urlencoded"; req.ContentLength = data.Length; req.UserAgent = "Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko/20100101 Firefox/11.0"; req.CookieContainer = new CookieContainer(); //发送POST数据 using (var outstream = req.GetRequestStream()) { outstream.Write(data, 0, data.Length); outstream.Flush(); } //关闭请求 req.GetResponse().Close(); cookies = req.CookieContainer; //保存cookies string cookiesstr = req.CookieContainer.GetCookieHeader(req.RequestUri); //字符串形式的cookies //重新请求网页 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); if (Info.Proxy != null) { request.Proxy = Info.Proxy; } //设置cookies request.CookieContainer = cookies; //获取网页源代码 src = Network.GetHtmlSource(request, Encoding.UTF8); } #endregion //取得视频标题 Regex rTitle = new Regex(@"<title>(?<title>.*)</title>"); Match mTitle = rTitle.Match(src); //文件名称 string title = mTitle.Groups["title"].Value.Replace("- 嗶哩嗶哩", "").Replace("- ( ゜- ゜)つロ", "").Replace("乾杯~", "").Replace("- bilibili.tv", "").Trim(); //取得子标题 Regex rSubTitle = new Regex(@"<option value='(?<part>.+?\.html)'(| selected)>(?<content>.+?)</option>"); MatchCollection mSubTitles = rSubTitle.Matches(src); //如果存在下拉列表框 if (mSubTitles.Count > 0) { //确定当前视频的子标题 foreach (Match item in mSubTitles) { if (suburl == item.Groups["part"].Value) { title = title + " - " + item.Groups["content"].Value; break; } } //如果需要解析关联下载项 //解析关联项需要同时满足的条件: //1.这个任务不是被其他任务所添加的 //2.用户设置了“解析关联项” if (!Info.IsBeAdded) { if (Info.ParseRelated) { //准备(地址-标题)字典 var dict = new Dictionary <string, string>(); foreach (Match item in mSubTitles) { if (suburl != item.Groups["part"].Value) { dict.Add(url.Replace(suburl, item.Groups["part"].Value), item.Groups["content"].Value); } } //用户选择任务 var ba = new Collection <string>(); if (!disableDialog) { ba = ToolForm.CreateMultiSelectForm(dict, Info.AutoAnswer, "bilibili"); } //根据用户选择新建任务 foreach (string u in ba) { //新建任务 delegates.NewTask(new ParaNewTask(Info.BasePlugin, u, this.Info)); } } } } Info.Title = title; //过滤非法字符 title = Tools.InvalidCharacterFilter(title, ""); //重新设置保存目录(生成子文件夹) if (!Info.SaveDirectory.ToString().EndsWith(title)) { string newdir = Path.Combine(Info.SaveDirectory.ToString(), title); if (!Directory.Exists(newdir)) { Directory.CreateDirectory(newdir); } Info.SaveDirectory = new DirectoryInfo(newdir); } //清空地址 Info.FilePath.Clear(); Info.SubFilePath.Clear(); //视频id string id = ""; //分析id和视频存放站点(type) //取得"bofqi块的源代码 Regex rEmbed = new Regex("<div class=\"scontent\" id=\"bofqi\">(?<content>.*?)</div>", RegexOptions.Singleline); Match mEmbed = rEmbed.Match(src); string embedSrc = mEmbed.Groups["content"].Value.Replace("type=\"application/x-shockwave-flash\"", ""); //检查"file"参数 Regex rFile = new Regex("file=(\"|)(?<file>.+?)(\"|&)"); Match mFile = rFile.Match(embedSrc); //取得Flash地址 Regex rFlash = new Regex("src=\"(?<flash>.*?\\.swf)\""); Match mFlash = rFlash.Match(embedSrc); //取得id值 Regex rId = new Regex(@"(?<idname>(\w{0,2}id|data))=(?<id>([\w\-]+|$http://.+?$))".Replace("$", "\"")); Match mId = rId.Match(embedSrc); //取得ID id = mId.Groups["id"].Value; //取得type值 type = mId.Groups["idname"].Value; //解析器的解析结果 ParseResult pr = null; //如果不是“仅下载字幕” if (Info.DownSub != DownloadSubtitleType.DownloadSubtitleOnly) { if (mFile.Success) //如果有file参数 { string fileurl = mFile.Groups["file"].Value; videos = new string[] { fileurl }; } else if (mId.Success) //如果是普通的外链 { //检查外链 switch (type) { case "qid": //QQ视频 //解析视频 QQVideoParser parserQQ = new QQVideoParser(); pr = parserQQ.Parse(new ParseRequest() { Id = id, Proxy = Info.Proxy, AutoAnswers = Info.AutoAnswer }); videos = pr.ToArray(); break; case "ykid": //优酷视频 //解析视频 YoukuParser parserYouKu = new YoukuParser(); pr = parserYouKu.Parse(new ParseRequest() { Id = id, Proxy = Info.Proxy, AutoAnswers = Info.AutoAnswer }); videos = pr.ToArray(); break; case "uid": //土豆视频 //解析视频 TudouParser parserTudou = new TudouParser(); pr = parserTudou.Parse(new ParseRequest() { Id = id, Proxy = Info.Proxy, AutoAnswers = Info.AutoAnswer }); videos = pr.ToArray(); break; case "data": //Flash游戏 id = id.Replace("\"", ""); videos = new string[] { id }; break; default: //新浪视频 SinaVideoParser parserSina = new SinaVideoParser(); pr = parserSina.Parse(new ParseRequest() { Id = id, Proxy = Info.Proxy, AutoAnswers = Info.AutoAnswer }); videos = pr.ToArray(); break; } } else //如果是游戏 { string flashurl = mFlash.Groups["flash"].Value; videos = new string[] { flashurl }; } Info.videos = videos; return(true); //下载视频 //确定视频共有几个段落 Info.PartCount = videos.Length; //------------分段落下载------------ for (int i = 0; i < Info.PartCount; i++) { Info.CurrentPart = i + 1; //取得文件后缀名 string ext = Tools.GetExtension(videos[i]); if (string.IsNullOrEmpty(ext)) { if (string.IsNullOrEmpty(Path.GetExtension(videos[i]))) { ext = ".flv"; } else { ext = Path.GetExtension(videos[i]); } } if (ext == ".hlv") { ext = ".flv"; } //设置当前DownloadParameter if (Info.PartCount == 1) { currentParameter = new DownloadParameter() { //文件名 例: c:\123(1).flv FilePath = Path.Combine(Info.SaveDirectory.ToString(), title + ext), //文件URL Url = videos[i], //代理服务器 Proxy = Info.Proxy, //提取缓存 ExtractCache = Info.ExtractCache, ExtractCachePattern = "fla*.tmp" }; } else { currentParameter = new DownloadParameter() { //文件名 例: c:\123(1).flv FilePath = Path.Combine(Info.SaveDirectory.ToString(), title + "(" + (i + 1).ToString() + ")" + ext), //文件URL Url = videos[i], //代理服务器 Proxy = Info.Proxy, //提取缓存 ExtractCache = Info.ExtractCache, ExtractCachePattern = "fla*.tmp" }; } //添加文件路径到List<>中 Info.FilePath.Add(currentParameter.FilePath); //下载文件 bool success; //提示更换新Part delegates.NewPart(new ParaNewPart(this.Info, i + 1)); //下载视频 try { success = Network.DownloadFile(currentParameter, this.Info); if (!success) //未出现错误即用户手动停止 { return(false); } } catch (Exception ex) //下载文件时出现错误 { //如果此任务由一个视频组成,则报错(下载失败) if (Info.PartCount == 1) { throw ex; } else //否则继续下载,设置“部分失败”状态 { Info.PartialFinished = true; Info.PartialFinishedDetail += "\r\n文件: " + currentParameter.Url + " 下载失败"; } } } //end for } //end 判断是否下载视频 //下载弹幕 bool comment = DownloadComment(title, id); //生成AcPlay文件 string acplay = GenerateAcplayConfig(pr, title); if (!comment) { Info.PartialFinished = true; Info.PartialFinishedDetail += "\r\n弹幕文件文件下载失败"; } //支持导出列表 StringBuilder sb = new StringBuilder(videos.Length * 2); foreach (string item in videos) { sb.Append(item); sb.Append("|"); } if (Info.Settings.ContainsKey("ExportUrl")) { Info.Settings["ExportUrl"] = sb.ToString(); } else { Info.Settings.Add("ExportUrl", sb.ToString()); } //支持AcPlay if (Info.Settings.ContainsKey("AcPlay")) { Info.Settings["AcPlay"] = acplay; } else { Info.Settings.Add("AcPlay", acplay); } } catch (Exception ex) { Info.Settings["user"] = ""; Info.Settings["password"] = ""; throw ex; } return(true); }
/// <summary> /// 下载视频 /// </summary> /// <returns></returns> public override bool Download() { //开始下载 delegates.TipText(new ParaTipText(this.Info, "正在分析视频地址")); //修正井号 Info.Url = Info.Url.TrimEnd('#'); //修正简写URL if (Regex.Match(Info.Url, @"^ac\d+$").Success) { Info.Url = "http://www.acfun.tv/v/" + Info.Url; } //修正index.html if (!Info.Url.EndsWith(".html")) { if (Info.Url.EndsWith("/")) { Info.Url += "index.html"; } else { Info.Url += "/index.html"; } } string url = Info.Url; //取得子页面文件名(例如"index_123.html") string suburl = Regex.Match(Info.Url, @"ac\d+/(?<part>index\.html|index_\d+\.html)").Groups["part"].Value; //取得AC号和子编号 Match mACNumber = Regex.Match(Info.Url, @"(?<ac>ac\d+)/index(_(?<sub>\d+)|)\.html"); Settings["ACNumber"] = mACNumber.Groups["ac"].Value; Settings["ACSubNumber"] = mACNumber.Groups["sub"].Success ? mACNumber.Groups["sub"].Value : "1"; //设置自定义文件名 Settings["CustomFileName"] = AcFunPlugin.DefaultFileNameFormat; if (Info.BasePlugin.Configuration.ContainsKey("CustomFileName")) { Settings["CustomFileName"] = Info.BasePlugin.Configuration["CustomFileName"]; } //是否通过【自动应答】禁用对话框 bool disableDialog = false; if (Info.AutoAnswer != null) { foreach (var item in Info.AutoAnswer) { if (item.Prefix == "acfun") { if (item.Identify == "auto") { disableDialog = true; } break; } } } try { //取得网页源文件 string src = Network.GetHtmlSource(url, Encoding.UTF8, Info.Proxy); //分析id和视频存放站点(type) string type; string id = ""; //视频id //string ot = ""; //视频子id //取得embed块的源代码 Regex rEmbed = new Regex(@"\<div id=""area-player""\>.+?\</div\>", RegexOptions.Singleline); Match mEmbed = rEmbed.Match(src); string embedSrc = mEmbed.ToString().Replace("type=\"application/x-shockwave-flash\"", ""); //检查是否为Flash游戏 Regex rFlash = new Regex(@"src=""(?<player>.+?)\.swf"""); Match mFlash = rFlash.Match(embedSrc); #region 取得当前Flash播放器地址 //脚本地址 string playerScriptUrl = "http:" + Regex.Match(src, @"(?<=<script src="")//static\.acfun\.tv/dotnet/\d+/script/article\.js(?="">)").Value + @"?_version=12289360"; //脚本源代码 string playerScriptSrc = Network.GetHtmlSource(playerScriptUrl, Encoding.UTF8, Info.Proxy); //swf文件地址 string playerUrl = Regex.Match(playerScriptSrc, @"http://.+?swf").Value; //添加到插件设置中 if (Info.Settings.ContainsKey("PlayerUrl")) { Info.Settings["PlayerUrl"] = playerUrl; } else { Info.Settings.Add("PlayerUrl", playerUrl); } #endregion //如果是Flash游戏 if (mFlash.Success && !mFlash.Value.Contains("newflvplayer")) { type = "game"; } else { if (!embedSrc.Contains(@"text/javascript")) //旧版本 { //获取ID Regex rId = new Regex(@"(\?|amp;|"")id=(?<id>\w+)(?<ot>(-\w*|))"); Match mId = rId.Match(embedSrc); id = mId.Groups["id"].Value; if (Info.Settings.ContainsKey("cid")) { Info.Settings["cid"] = id; } else { Info.Settings.Add("cid", id); } //取得type值 Regex rType = new Regex(@"type(|\w)=(?<type>\w*)"); Match mType = rType.Match(embedSrc); type = mType.Groups["type"].Value; if (type.Equals("video", StringComparison.CurrentCultureIgnoreCase)) { type = "sina"; } } else { //取得acfun id值 Regex rAcfunId = new Regex(@"'id':'(?<id>\d+)"); Match mAcfunId = rAcfunId.Match(embedSrc); string acfunid = mAcfunId.Groups["id"].Value; //获取跳转 string getvideobyid = Network.GetHtmlSource("http://www.acfun.tv/api/getVideoByID.aspx?vid=" + acfunid, Encoding.UTF8); //将信息添加到Setting中 Regex rVideoInfo = new Regex(@"""(?<key>.+?)"":(""|)(?<value>.+?)(""|)[,|}]"); MatchCollection mcVideoInfo = rVideoInfo.Matches(getvideobyid); foreach (Match mVideoInfo in mcVideoInfo) { string key = mVideoInfo.Groups["key"].Value; string value = mVideoInfo.Groups["value"].Value; if (Info.Settings.ContainsKey(key)) { Info.Settings[key] = value; } else { Info.Settings.Add(key, value); } } id = Info.Settings["vid"]; type = Info.Settings["vtype"]; } } //取得视频标题 Regex rTitle = new Regex(@"<title>(?<title>.*)</title>"); Match mTitle = rTitle.Match(src); string title = mTitle.Groups["title"].Value.Replace(" - Acfun", "").Replace(" - 天下漫友是一家", ""); //取得所有子标题 Regex rSubTitle = new Regex(@"<a class=""pager pager-article"" href=""(?<part>.+?)"">(?<content>.+?)</a>"); MatchCollection mSubTitles = rSubTitle.Matches(src); //如果存在下拉列表框 if (mSubTitles.Count > 0) { //解析关联项需要同时满足的条件: //1.这个任务不是被其他任务所添加的 //2.用户设置了“解析关联项” if (!Info.IsBeAdded) { if (Info.ParseRelated) { //准备(地址-标题)字典 var dict = new Dictionary <string, string>(); foreach (Match item in mSubTitles) { dict.Add(url.Replace(suburl, item.Groups["part"].Value), item.Groups["content"].Value); } //用户选择任务 var ba = new Collection <string>(); if (!disableDialog) { ba = ToolForm.CreateMultiSelectForm(dict, Info.AutoAnswer, "acfun"); } //根据用户选择新建任务 foreach (string u in ba) { //新建任务 delegates.NewTask(new ParaNewTask(Info.BasePlugin, u, this.Info)); } } } } Info.Title = title; //过滤非法字符 title = Tools.InvalidCharacterFilter(title, ""); //视频地址数组 string[] videos = null; //清空地址 Info.FilePath.Clear(); Info.SubFilePath.Clear(); //下载弹幕 bool comment = DownloadSubtitle(title); if (!comment) { Info.PartialFinished = true; Info.PartialFinishedDetail += "\r\n弹幕文件文件下载失败"; } //解析器的解析结果 ParseResult pr = null; //如果允许下载视频 if ((Info.DownloadTypes & DownloadType.Video) != 0) { //检查type值 switch (type) { case "sina": //新浪视频 //解析视频 SinaVideoParser parserSina = new SinaVideoParser(); pr = parserSina.Parse(new ParseRequest() { Id = id, Proxy = Info.Proxy, AutoAnswers = Info.AutoAnswer }); videos = pr.ToArray(); break; case "qq": //QQ视频 //解析视频 QQVideoParser parserQQ = new QQVideoParser(); pr = parserQQ.Parse(new ParseRequest() { Id = id, Proxy = Info.Proxy, AutoAnswers = Info.AutoAnswer }); videos = pr.ToArray(); break; case "youku": //优酷视频 //解析视频 YoukuParser parserYouKu = new YoukuParser(); pr = parserYouKu.Parse(new ParseRequest() { Id = id, Proxy = Info.Proxy, AutoAnswers = Info.AutoAnswer }); videos = pr.ToArray(); break; case "tudou": //土豆视频 TudouParser parserTudou = new TudouParser(); pr = parserTudou.Parse(new ParseRequest() { Id = id, Proxy = Info.Proxy, AutoAnswers = Info.AutoAnswer }); videos = pr.ToArray(); break; case "game": //flash游戏 videos = new string[] { mFlash.Groups["player"].Value }; break; } Info.videos = videos; return(true); //下载视频 //确定视频共有几个段落 Info.PartCount = videos.Length; //------------分段落下载------------ for (int i = 0; i < Info.PartCount; i++) { Info.CurrentPart = i + 1; //取得文件后缀名 string ext = Tools.GetExtension(videos[i]); if (string.IsNullOrEmpty(ext)) { if (string.IsNullOrEmpty(Path.GetExtension(videos[i]))) { ext = ".flv"; } else { ext = Path.GetExtension(videos[i]); } } if (ext == ".hlv") { ext = ".flv"; } //设置文件名 var renamehelper = new CustomFileNameHelper(); string filename = renamehelper.CombineFileName(Settings["CustomFileName"], title, "", Info.PartCount == 1 ? "" : Info.CurrentPart.ToString(), ext.Replace(".", ""), Info.Settings["ACNumber"], Info.Settings["ACSubNumber"]); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); //生成父文件夹 if (!Directory.Exists(Path.GetDirectoryName(filename))) { Directory.CreateDirectory(Path.GetDirectoryName(filename)); } //设置当前DownloadParameter currentParameter = new DownloadParameter() { //文件名 FilePath = filename, //文件URL Url = videos[i], //代理服务器 Proxy = Info.Proxy, //提取缓存 ExtractCache = Info.ExtractCache, ExtractCachePattern = "fla*.tmp" }; //设置代理服务器 currentParameter.Proxy = Info.Proxy; //添加文件路径到List<>中 Info.FilePath.Add(currentParameter.FilePath); //下载文件 bool success = false; //提示更换新Part delegates.NewPart(new ParaNewPart(this.Info, i + 1)); //下载视频 try { success = Network.DownloadFile(currentParameter, this.Info); if (!success) //未出现错误即用户手动停止 { return(false); } } catch (Exception ex) //下载文件时出现错误 { //如果此任务由一个视频组成,则报错(下载失败) if (Info.PartCount == 1) { throw ex; } else //否则继续下载,设置“部分失败”状态 { Info.PartialFinished = true; Info.PartialFinishedDetail += "\r\n文件: " + currentParameter.Url + " 下载失败"; } } } //end for } //end 判断是否下载视频 //如果插件设置中没有GenerateAcPlay项,或此项设置为true则生成.acplay快捷方式 if (!Info.BasePlugin.Configuration.ContainsKey("GenerateAcPlay") || Info.BasePlugin.Configuration["GenerateAcPlay"] == "true") { //生成AcPlay文件 string acplay = GenerateAcplayConfig(pr, title); //支持AcPlay直接播放 Info.Settings["AcPlay"] = acplay; } //支持导出列表 if (videos != null) { StringBuilder sb = new StringBuilder(videos.Length * 2); foreach (string item in videos) { sb.Append(item); sb.Append("|"); } if (Info.Settings.ContainsKey("ExportUrl")) { Info.Settings["ExportUrl"] = sb.ToString(); } else { Info.Settings.Add("ExportUrl", sb.ToString()); } } } catch (Exception ex) { throw ex; } //下载成功完成 return(true); }
public bool Download() { //开始下载 delegates.TipText(new ParaTipText(this.Info, "正在分析漫画地址")); if (currentParameter != null) { //将停止flag设置为true currentParameter.IsStop = false; } try { //取得Url源文件 string src = Network.GetHtmlSource(Info.Url, Encoding.GetEncoding("UTF-8"), Info.Proxy); //要下载的Url列表 var subUrls = new Collection <string>(); Regex regChapter = new Regex("\"chapters\">[\\s|\\S]*?<\\/div>"); // 确定是整部漫画还是单独一话 if (regChapter.Match(src).Success) { //尼玛是整部漫画.. Match value = regChapter.Match(src); src = value.Value; regChapter = new Regex("href=\"(?'link'[^>]+)\">(?'title'[^<]+)"); value = regChapter.Match(src); string title = value.Groups["title"].Value.Trim(); int MaxCount = ((int)float.Parse(Path.GetFileName(value.Groups["link"].Value))); string baseLink = value.Groups["link"].Value; baseLink = baseLink.Substring(0, baseLink.LastIndexOf('/') + 1); title = title.Replace(float.Parse(Path.GetFileName(value.Groups["link"].Value)).ToString(), ""); //填充字典 var dict = new Dictionary <string, string>(); while (MaxCount > 0) { dict.Add(baseLink + MaxCount.ToString(), title + MaxCount.ToString()); MaxCount--; } //选择下载哪部漫画 subUrls = ToolForm.CreateMultiSelectForm(dict, Info.AutoAnswer, "Goodmanga"); //如果用户没有选择任何章节 if (subUrls.Count == 0) { return(false); } } else { subUrls.Add(Info.Url); } Info.PartCount = subUrls.Count; Info.CurrentPart = 0; foreach (string url in subUrls) { Info.CurrentPart++; //提示更换新Part delegates.NewPart(new ParaNewPart(this.Info, Info.CurrentPart)); if (DownloadChapterComic(url) == false) { return(false); } } } catch { } //下载成功完成 currentParameter.DoneBytes = currentParameter.TotalLength; return(true); }
//下载视频 public bool Download() { //开始下载 delegates.TipText(new ParaTipText(this.Info, "正在分析漫画地址")); if (currentParameter != null) { //将停止flag设置为true currentParameter.IsStop = false; } try { //取得Url源文件 string src = Network.GetHtmlSource(Info.Url, Encoding.GetEncoding("GB2312"), Info.Proxy); //要下载的Url列表 var subUrls = new Collection <string>(); //分析漫画id和lid Regex r = new Regex(@"http://(www\.|)imanhua\.com/comic/(?<id>\d+)(/list_(?<lid>\d+)\.html|)"); Match m = r.Match(Info.Url); string id = m.Groups["id"].Value; string lid = m.Groups["lid"].Value; #region 确定是整部漫画还是单独一话 //lid为空 则为整部漫画 if (string.IsNullOrEmpty(lid)) { //取得所有漫画的列表 Regex rAllComics = new Regex(@"<a href=$(?<suburl>/comic/\d+/list_\d+.html)$ title=$(?<title>.*?)$".Replace("$", "\"")); MatchCollection mcAllComics = rAllComics.Matches(src); //填充字典 var dict = new Dictionary <string, string>(); foreach (Match item in mcAllComics) { dict.Add("http://www.imanhua.com" + item.Groups["suburl"].Value, item.Groups["title"].Value); } //选择下载哪部漫画 //提取用户上次选择的章节 如果配置中有Chosen项 if (Info.Settings.ContainsKey("Chosen") && !string.IsNullOrEmpty(Info.Settings["Chosen"])) { foreach (var u in Info.Settings["Chosen"].Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries)) { subUrls.Add(u); } } else { subUrls = ToolForm.CreateMultiSelectForm(dict, Info.AutoAnswer, "imanhua"); } //如果用户没有选择任何章节 if (subUrls.Count == 0) { return(false); } //取得漫画标题 Regex rTitle = new Regex(@"\<h1\>(?<title>.*)\<\/h1\>"); Match mTitle = rTitle.Match(src); string title = mTitle.Groups["title"].Value; //过滤标题中的非法字符 title = Tools.InvalidCharacterFilter(title, ""); Info.Title = title; } else //如果不是整部漫画则添加此单话url { subUrls.Add(Info.Url); //取得漫画标题 //取得上级页面的url Regex rGetParent = new Regex(@"http://www\.imanhua\.com/comic/\d+/"); Match mGetParent = rGetParent.Match(Info.Url); string parentUrl = mGetParent.ToString(); //取得源代码并分析 string pSrc = Network.GetHtmlSource(parentUrl, Encoding.GetEncoding("GB2312"), Info.Proxy); //取得漫画标题 Regex rTitle = new Regex(@"\<h1\>(?<title>.*)\<\/h1\>"); Match mTitle = rTitle.Match(pSrc); string title = mTitle.Groups["title"].Value; //过滤标题中的非法字符 title = Tools.InvalidCharacterFilter(title, ""); Info.Title = title; } //end if #endregion //将用户选择的漫画章节存入配置 var sbChosen = new StringBuilder(); foreach (var suburl in subUrls) { sbChosen.Append(suburl + "|"); } Info.Settings["Chosen"] = sbChosen.ToString(); #region 择服务器 //取得服务器配置文件 string serverjs = Network.GetHtmlSource(@"http://www.imanhua.com/v2/config/config.js", Encoding.GetEncoding("GB2312"), Info.Proxy); Regex rServer = new Regex(@"arrHost\[\d+\][ =""'\[]+(?<server>.+?)[""', ]+(?<ip>.+?)[""']\]"); MatchCollection mServers = rServer.Matches(serverjs); //添加到数组中 Dictionary <string, string> servers = new Dictionary <string, string>(); foreach (Match item in mServers) { if (!servers.ContainsKey(item.Groups["ip"].Value)) { servers.Add(item.Groups["ip"].Value, item.Groups["server"].Value); } } //选择服务器 string serverName = ToolForm.CreateSingleSelectForm("", servers, "", Info.AutoAnswer, "imanhua"); #endregion #region 载漫画 //建立文件夹 string mainDir = Info.SaveDirectory + (Info.SaveDirectory.ToString().EndsWith(@"\") ? "" : @"\") + Info.Title; //确定漫画共有几个段落 Info.PartCount = subUrls.Count; int i = 0; //分段落下载 foreach (string surl in subUrls) { Info.CurrentPart = i + 1; //提示更换新Part delegates.NewPart(new ParaNewPart(this.Info, i + 1)); //分析漫画id和lid Regex rSubUrl = new Regex(@"http://(www\.|)imanhua\.com/comic/(?<bid>\d+)(/list_(?<cid>\d+)\.html|)"); Match mSubUrl = rSubUrl.Match(surl); string bookId = mSubUrl.Groups["bid"].Value; string chapterId = mSubUrl.Groups["cid"].Value; //地址数组 List <string> fileUrls = new List <string>(); //分析源代码,取得下载地址 WebClient wc = new WebClient(); //if (Info.Proxy != null) wc.Proxy = Info.Proxy; //取得源代码 byte[] buff = wc.DownloadData(surl); string cookie = wc.ResponseHeaders.Get("Set-Cookie"); string source = Encoding.GetEncoding("GB2312").GetString(buff); //取得标题 //Regex rTitle = new Regex(@"<span id=""position"">.+?>> <a href="".+?"">(?<title>.+?)</a> >> <a href="".+?"">(?<subtitle>.+?)</a></span>"); //Match mTitle = rTitle.Match(source); //string subTitle = mTitle.Groups["subtitle"].Value; string subTitle = Regex.Match(source, @"(?<=<h2>).+?(?=</h2>)").Value; //过滤子标题中的非法字符 subTitle = Tools.InvalidCharacterFilter(subTitle, ""); //合并本地路径(文件夹) string subDir = mainDir + @"\" + subTitle; //创建文件夹 Directory.CreateDirectory(subDir); ////检查是否是老版本 //if (int.Parse(chapterId) > 7910) //7910之后为新版本 //{ //如果使用动态生成 if (source.Contains(@"var cInfo={")) { //获取所有文件名 Regex rFileName = new Regex(@"(?<="")[^,]+(?="")"); MatchCollection mcFileNames = rFileName.Matches(Regex.Match(source, @"(?<=""files"":\[).+?(?=\])").Value); foreach (Match file in mcFileNames) { if (file.Value.StartsWith("/")) { fileUrls.Add(serverName + file.Value); } else { fileUrls.Add(serverName + "/Files/Images/" + bookId + "/" + chapterId + "/" + file.Value); } } } else { //获取所有文件名 //获取页面HTML中的js段 Regex rJsFiles = new Regex(@"(?<=var pic=\[).+?(?=\])"); string jsFiles = rJsFiles.Match(source).Value; //获取所有图片文件 Regex rFileName = new Regex(@"(?<="")[^,]+(?="")"); MatchCollection mcFileNames = rFileName.Matches(jsFiles); foreach (Match file in mcFileNames) { fileUrls.Add(serverName + (file.Value.StartsWith("/") ? file.Value : "/" + file.Value)); } } //输出真实地址 StringBuilder sb = new StringBuilder(fileUrls.Count); foreach (var file in fileUrls) { sb.Append(file + "|"); } Info.Settings["ExportUrl"] = sb.ToString(); sb = null; //设置下载长度 currentParameter.TotalLength = fileUrls.Count; //下载文件! for (int j = 0; j < fileUrls.Count; j++) { if (currentParameter.IsStop) { return(false); } try { wc.Headers.Add("Referer", subUrls[i]); wc.Headers.Add("Cookie", cookie); byte[] content = wc.DownloadData(fileUrls[j]); string fn = Path.GetFileName(fileUrls[j]); File.WriteAllBytes(Path.Combine(subDir, fn), content); } catch { } //end try currentParameter.DoneBytes = j; } // end for i++; } //end foreach } //end try catch (Exception ex) //出现错误即下载失败 { throw ex; } //end try #endregion //下载成功完成 currentParameter.DoneBytes = currentParameter.TotalLength; return(true); } //end DownloadVideo
public bool Download() { //开始下载 delegates.TipText(new ParaTipText(this.Info, "正在分析動畫下載位址")); Regex regChapter = new Regex("http://.+/v/[^-]+-(?<param1>[0-9])-(?<param2>[0-9][0-9]?).html"); Match linkname = regChapter.Match(Info.Url); //要下载的Url列表 var subUrls = new Collection <string>(); if (linkname.Success == false) { //尼玛是整部 regChapter = new Regex("http://www.dm530.com/show/(?<value>[^.]+).html"); linkname = regChapter.Match(Info.Url); //取得Url源文件 string src = Network.GetHtmlSource(Info.Url, Encoding.GetEncoding("GBK"), Info.Proxy); //填充字典 var dict = new Dictionary <string, string>(); int chapter_start = src.IndexOf("class=\"on\""); while (chapter_start > 0) { int chapter_end = src.IndexOf("class=\"on\"", chapter_start + 1); if (chapter_end < 0) { break; } string sub_src = src.Substring(chapter_start, chapter_end - chapter_start); regChapter = new Regex("class=\"on\">(?<source_name>[^<]+)</li>"); Match item = regChapter.Match(sub_src); if (item.Success == false) { break; } string souce_name = item.Groups["source_name"].Value; string chapter = "title='(?<chapter_name>[^']+)' href='(?<link_url>[^']+)'"; regChapter = new Regex(chapter); item = regChapter.Match(sub_src); while (item.Success) { string url = "http://www.dm530.com" + item.Groups["link_url"].Value; string chapter_name = souce_name + "-" + item.Groups["chapter_name"].Value; dict.Add(url.Trim(), chapter_name); // first match is "hello world"!! but this turns out to be an infinite loop item = item.NextMatch(); } chapter_start = chapter_end; } if (dict.Count <= 0) { return(false); } //选择下载哪部漫画 subUrls = ToolForm.CreateMultiSelectForm(dict, Info.AutoAnswer, "dm530"); //如果用户没有选择任何章节 if (subUrls.Count == 0) { return(false); } } else { subUrls.Add(Info.Url); } Info.PartCount = subUrls.Count; Info.CurrentPart = 0; foreach (string url in subUrls) { //提示更换新Part delegates.NewPart(new ParaNewPart(this.Info, Info.CurrentPart)); regChapter = new Regex("http://.+/[^-]+-(?<param1>[0-9])-(?<param2>[0-9][0-9]?).html"); Match urlname = regChapter.Match(url); string chaper_src = Network.GetHtmlSource(url, Encoding.GetEncoding("GBK"), Info.Proxy); string title_name = "NoName"; regChapter = new Regex("<meta name=\"title\" content=\"(?<title_name>[^\"]+)\">"); Match item = regChapter.Match(chaper_src); if (item.Success) { title_name = item.Groups["title_name"].Value; } regChapter = new Regex("/playdata/(?<js_name>[^\"]+)"); item = regChapter.Match(chaper_src); if (item.Success == false) { continue; } string js_url = "http://www.dm530.com/playdata/" + item.Groups["js_name"].Value; string js_src = Network.GetHtmlSource(js_url, Encoding.GetEncoding("GBK"), Info.Proxy); int json_start = js_src.IndexOf("["); int json_end = js_src.LastIndexOf("]"); js_src = js_src.Substring(json_start, json_end - json_start + 1); System.IO.File.WriteAllText(@"d:\dm530.txt", js_src); //取得视频信息 List <Dm530Video> chapterinfo = new List <Dm530Video>(); JArray jarr = JArray.Parse(js_src); int videoidx = -1; foreach (var jitem in jarr.Children()) { foreach (var jsubitem in jitem.Children()) { if (jsubitem.Type == JTokenType.String) { Dm530Video video = new Dm530Video(); video.souce = jsubitem.ToString(); videoidx++; chapterinfo.Add(video); } else if (jsubitem.Type == JTokenType.Array) { chapterinfo [videoidx].info = jsubitem.ToObject <List <string> >(); } } } int param1 = int.Parse(urlname.Groups["param1"].Value); int param2 = int.Parse(urlname.Groups["param2"].Value); DownloadChapter(chapterinfo[param1].info[param2], title_name); } return(true); }
/// <summary> /// 下载视频 /// </summary> public override bool Download() { //开始下载 TipText("正在分析视频地址"); //修正井号 Info.Url = Info.Url.ToLower().TrimEnd('#'); //修正旧版URL Info.Url = Info.Url.Replace("bilibili.tv", "bilibili.com"); Info.Url = Info.Url.Replace("bilibili.us", "bilibili.com"); Info.Url = Info.Url.Replace("bilibili.smgbb.cn", "www.bilibili.com"); Info.Url = Info.Url.Replace("bilibili.kankanews.com", "www.bilibili.com"); //修正简写URL if (Regex.Match(Info.Url, @"^av\d{2,6}$").Success) { Info.Url = "http://www.bilibili.com/video/" + Info.Url + "/"; } //修正index_1.html if (!Info.Url.EndsWith(".html")) { if (Info.Url.EndsWith("/")) { Info.Url += "index_1.html"; } else { Info.Url += "/index_1.html"; } } string url = Info.Url; //取得子页面文件名(例如"/video/av12345/index_123.html") //string suburl = Regex.Match(Info.Url, @"bilibili\.kankanews\.com(?<part>/video/av\d+/index_\d+\.html)").Groups["part"].Value; string suburl = Regex.Match(Info.Url, @"www\.bilibili\.com(?<part>/video/av\d+/index_\d+\.html)").Groups["part"].Value; //取得AV号和子编号 //Match mAVNumber = Regex.Match(Info.Url, @"(?<av>av\d+)/index_(?<sub>\d+)\.html"); Match mAVNumber = BilibiliPlugin.RegexBili.Match(Info.Url); if (!mAVNumber.Success) { mAVNumber = BilibiliPlugin.RegexAcg.Match(Info.Url); } Settings["AVNumber"] = mAVNumber.Groups["id"].Value; Settings["AVSubNumber"] = mAVNumber.Groups["page"].Value; Settings["AVSubNumber"] = string.IsNullOrEmpty(Settings["AVSubNumber"]) ? "1" : Settings["AVSubNumber"]; //设置自定义文件名 Settings["CustomFileName"] = BilibiliPlugin.DefaultFileNameFormat; if (Info.BasePlugin.Configuration.ContainsKey("CustomFileName")) { Settings["CustomFileName"] = Info.BasePlugin.Configuration["CustomFileName"]; } //是否通过【自动应答】禁用对话框 bool disableDialog = AutoAnswer.IsInAutoAnswers(Info.AutoAnswer, "bilibili", "auto"); //视频地址数组 string[] videos = null; try { //解析关联项需要同时满足的条件: //1.这个任务不是被其他任务所添加的 //2.用户设置了“解析关联项” if (!Info.IsBeAdded || Info.ParseRelated) { //取得网页源文件 string src = Network.GetHtmlSource(url, Encoding.UTF8, Info.Proxy); string subtitle = ""; //取得子标题 Regex rSubTitle = new Regex(@"<option value='(?<part>.+?\.html)'( selected)?>(?<content>.+?)</option>"); MatchCollection mSubTitles = rSubTitle.Matches(src); //如果存在下拉列表框 if (mSubTitles.Count > 0) { //确定当前视频的子标题 foreach (Match item in mSubTitles) { if (suburl == item.Groups["part"].Value) { subtitle = item.Groups["content"].Value; break; } } //准备(地址-标题)字典 var dict = new Dictionary <string, string>(); foreach (Match item in mSubTitles) { if (suburl != item.Groups["part"].Value) { dict.Add(url.Replace(suburl, item.Groups["part"].Value), item.Groups["content"].Value); } } //用户选择任务 var ba = new Collection <string>(); if (!disableDialog) { ba = ToolForm.CreateMultiSelectForm(dict, Info.AutoAnswer, "bilibili"); } //根据用户选择新建任务 foreach (string u in ba) { NewTask(u); } } } //获取视频信息API var ts = Convert.ToInt64((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0)).TotalMilliseconds); var apiAddress = string.Format(@"http://api.bilibili.cn/view?appkey={0}&ts={1}&id={2}&page={3}", BilibiliPlugin.AppKey, ts, Settings["AVNumber"], Settings["AVSubNumber"]); //AcDown所使用的AppKey是旧AppKey,权限比新申请的要高,而且不需要加上sign验证 //如果将来要使用sign验证的话可以使用下面的代码来算出sign //但是这段代码目前加上后还是不能正确工作的状态,不知道为什么 //Tools.GetStringHash("appkey=" + BilibiliPlugin.AppKey + // "&id=" + Settings["AVNumber"] + // "&page=" + Settings["AVSubNumber"] + // "&ts=" + ts + // BilibiliPlugin.AppSecret)); var webrequest = (HttpWebRequest)WebRequest.Create(apiAddress); webrequest.Accept = @"application/json"; webrequest.UserAgent = "AcDown/" + Application.ProductVersion + " ([email protected])"; webrequest.Proxy = Info.Proxy; var viewSrc = Network.GetHtmlSource(webrequest, Encoding.UTF8); //登录获取API结果 if (viewSrc.Contains("no perm error")) { viewSrc = LoginApi(url, apiAddress, out m_cookieContainer); } AvInfo avInfo; try { //解析JSON avInfo = JsonConvert.DeserializeObject <AvInfo>(viewSrc); } catch { //由于接口原因,有时候虽然请求了json但是会返回XML格式(呃 var viewDoc = new XmlDocument(); viewDoc.LoadXml(viewSrc); avInfo = new AvInfo(); avInfo.title = viewDoc.SelectSingleNode(@"/info/title").InnerText.Replace("&", "&"); avInfo.partname = viewDoc.SelectSingleNode(@"/info/partname").InnerText.Replace("&", "&"); avInfo.cid = Regex.Match(viewSrc, @"(?<=\<cid\>)\d+(?=\</cid\>)", RegexOptions.IgnoreCase).Value; } //视频标题和子标题 string title = avInfo.title ?? ""; string stitle = avInfo.partname ?? ""; if (String.IsNullOrEmpty(stitle)) { Info.Title = title; stitle = title; } else { Info.Title = title + " - " + stitle; } //过滤非法字符 title = Tools.InvalidCharacterFilter(title, ""); stitle = Tools.InvalidCharacterFilter(stitle, ""); //清空地址 Info.FilePath.Clear(); Info.SubFilePath.Clear(); //CID Settings["chatid"] = avInfo.cid; //下载弹幕 DownloadComment(title, stitle, Settings["chatid"]); //解析器的解析结果 ParseResult pr = null; //如果允许下载视频 if ((Info.DownloadTypes & DownloadType.Video) != 0) { //var playurlSrc = Network.GetHtmlSource(@"http://interface.bilibili.tv/playurl?otype=xml&cid=" + Settings["chatid"] + "&type=flv", Encoding.UTF8); //var playurlDoc = new XmlDocument(); //playurlDoc.LoadXml(playurlSrc); //获得视频列表 var prRequest = new ParseRequest() { Id = Settings["chatid"], Proxy = Info.Proxy, AutoAnswers = Info.AutoAnswer, CookieContainer = m_cookieContainer }; pr = new BilibiliInterfaceParser().Parse(prRequest); videos = pr.ToArray(); //支持导出列表 if (videos != null) { StringBuilder sb = new StringBuilder(videos.Length * 2); foreach (string item in videos) { sb.Append(item); sb.Append("|"); } if (Settings.ContainsKey("ExportUrl")) { Settings["ExportUrl"] = sb.ToString(); } else { Settings.Add("ExportUrl", sb.ToString()); } } //下载视频 //确定视频共有几个段落 Info.PartCount = videos.Length; //------------分段落下载------------ for (int i = 0; i < Info.PartCount; i++) { Info.CurrentPart = i + 1; //取得文件后缀名 string ext = Tools.GetExtension(videos[i]); if (string.IsNullOrEmpty(ext)) { if (string.IsNullOrEmpty(Path.GetExtension(videos[i]))) { ext = ".flv"; } else { ext = Path.GetExtension(videos[i]); } } if (ext == ".hlv") { ext = ".flv"; } //设置文件名 var renamehelper = new CustomFileNameHelper(); string filename = renamehelper.CombineFileName(Settings["CustomFileName"], title, stitle, Info.PartCount == 1 ? "" : Info.CurrentPart.ToString(), ext.Replace(".", ""), Settings["AVNumber"], Settings["AVSubNumber"]); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); //生成父文件夹 if (!Directory.Exists(Path.GetDirectoryName(filename))) { Directory.CreateDirectory(Path.GetDirectoryName(filename)); } //设置当前DownloadParameter currentParameter = new DownloadParameter() { //文件名 例: c:\123(1).flv FilePath = filename, //文件URL Url = videos[i], //代理服务器 Proxy = Info.Proxy, //提取缓存 ExtractCache = Info.ExtractCache, ExtractCachePattern = "fla*.tmp" }; //添加文件路径到List<>中 Info.FilePath.Add(currentParameter.FilePath); //下载文件 bool success; //提示更换新Part delegates.NewPart(new ParaNewPart(this.Info, i + 1)); //下载视频 try { success = Network.DownloadFile(currentParameter, this.Info); if (!success) //未出现错误即用户手动停止 { return(false); } } catch //下载文件时出现错误 { //如果此任务由一个视频组成,则报错(下载失败) if (Info.PartCount == 1) { throw; } else //否则继续下载,设置“部分失败”状态 { Info.PartialFinished = true; Info.PartialFinishedDetail += "\r\n文件: " + currentParameter.Url + " 下载失败"; } } } //end for } //end 判断是否下载视频 //如果插件设置中没有GenerateAcPlay项,或此项设置为true则生成.acplay快捷方式 if (!Info.BasePlugin.Configuration.ContainsKey("GenerateAcPlay") || Info.BasePlugin.Configuration["GenerateAcPlay"] == "true") { //生成AcPlay文件 string acplay = GenerateAcplayConfig(pr, title, stitle); //支持AcPlay直接播放 Settings["AcPlay"] = acplay; } //生成视频自动合并参数 if (Info.FilePath.Count > 1 && !Info.PartialFinished) { Info.Settings.Remove("VideoCombine"); var arg = new StringBuilder(); foreach (var item in Info.FilePath) { arg.Append(item); arg.Append("|"); } var renamehelper = new CustomFileNameHelper(); string filename = renamehelper.CombineFileName(Settings["CustomFileName"], title, stitle, "", "mp4", Info.Settings["AVNumber"], Info.Settings["AVSubNumber"]); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); arg.Append(filename); Info.Settings["VideoCombine"] = arg.ToString(); } } catch { Settings["user"] = ""; Settings["password"] = ""; throw; } return(true); }
//下载视频 public override bool Download() { //开始下载 TipText("正在解析视频地址"); //解析专辑 if (Regex.IsMatch(Info.Url, TudouPlugin.regAlbumcover, RegexOptions.IgnoreCase)) { string source = Network.GetHtmlSource(Info.Url, Encoding.GetEncoding("GBK"), Info.Proxy); MatchCollection mcAlbumPlays = Regex.Matches(source.Replace(" ", "").Replace("\t", "").Replace("\r\n", ""), @"<h6class=""caption.+?(?<url>http://www\.tudou\.com/albumplay/[\w\-]+(/[\w\-]+|)\.html)"">(?<title>.+?)</a></h6>"); var plays = new Dictionary <string, string>(); foreach (Match mAlbumPlays in mcAlbumPlays) { string aUrl = mAlbumPlays.Groups["url"].Value; string aTitle = mAlbumPlays.Groups["title"].Value; plays.Add(aUrl, aTitle); } var chosen = ToolForm.CreateMultiSelectForm(plays, null, "tudou"); if (chosen.Count == 0) { throw new Exception("未从列表中选择任何视频"); } //修正当前url为用户选中的第一个url Info.Url = chosen[0]; //添加其他任务 for (int i = 1; i < chosen.Count; i++) { NewTask(chosen[i]); } } string url = Info.Url; //修正豆泡网址 if (Regex.Match(Info.Url, TudouPlugin.regDpProgramview).Success) { url = @"http://www.tudou.com/programs/view/" + Regex.Match(Info.Url, TudouPlugin.regDpProgramview).Groups["icode"].Value; } else if (Regex.IsMatch(Info.Url, TudouPlugin.regDpAlbumList)) { url = Info.Url.Replace("dp.tudou.com", "www.tudou.com"); url = url.Replace("/l/", "/listplay/"); url = url.Replace("/a/", "/albumplay/"); } //Settings["icode"] = Regex.Match(Info.Url, TudouPlugin.regProgramView).Groups["icode"].Value; string src = Network.GetHtmlSource(url, Encoding.GetEncoding("GBK"), Info.Proxy); //取得iid Settings["iid"] = Regex.Match(src.Replace(" ", ""), @"(?<=iid:)\d+").Value; //取得专辑标题 Settings["AlbumTitle"] = Regex.Match(src, @"(?<=atitle="").+?(?="")").Value ?? ""; //视频标题 Info.Title = Regex.Match(src, @"(?<=kw:( |)(""|')).+?(?=(""|'))").Value; Settings["title"] = Tools.InvalidCharacterFilter(Info.Title, ""); if (!string.IsNullOrEmpty(Settings["AlbumTitle"])) { Settings["title"] = Tools.InvalidCharacterFilter(Settings["AlbumTitle"], "") + Path.DirectorySeparatorChar + Settings["title"]; } //视频地址数组 string[] videos = null; //清空地址 Info.FilePath.Clear(); //调用土豆视频解析器 TudouParser parserTudou = new TudouParser(); var pr = parserTudou.Parse(new ParseRequest() { Id = Settings["iid"], Proxy = Info.Proxy, AutoAnswers = Info.AutoAnswer }); videos = pr.ToArray(); //下载弹幕 if ((Info.DownloadTypes & DownloadType.Subtitle) != 0) { //如果视频地址属于豆泡 if (Regex.IsMatch(Info.Url, TudouPlugin.regDpProgramview) || Regex.IsMatch(Info.Url, TudouPlugin.regDpAlbumList)) { TipText("正在下载弹幕文件"); try { var subfile = Path.Combine(Info.SaveDirectory.ToString(), Settings["title"] + ".json"); Info.SubFilePath.Clear(); Info.SubFilePath.Add(subfile); Network.DownloadFile(new DownloadParameter() { FilePath = subfile, Url = "http://comment.dp.tudou.com/comment/get/" + Settings["iid"] + "/vdn12d/", Proxy = Info.Proxy }); } catch { } } } //下载视频 //确定视频共有几个段落 Info.PartCount = videos.Length; TipText("正在开始下载视频文件"); //分段落下载 for (int i = 0; i < videos.Length; i++) { //取得文件后缀名 string ext = Tools.GetExtension(videos[i]); if (ext == ".f4v") { ext = ".flv"; } //设置当前DownloadParameter if (Info.PartCount == 1) //如果只有一段 { currentParameter = new DownloadParameter() { //文件名 例: c:\123(1).flv FilePath = Path.Combine(Info.SaveDirectory.ToString(), Settings["title"] + ext), //文件URL Url = videos[i], //代理服务器 Proxy = Info.Proxy }; } else //如果分段有多段 { currentParameter = new DownloadParameter() { //文件名 例: c:\123(1).flv FilePath = Path.Combine(Info.SaveDirectory.ToString(), Settings["title"] + "(" + (i + 1).ToString() + ")" + ext), //文件URL Url = videos[i], //代理服务器 Proxy = Info.Proxy }; } //添加文件路径到List<>中 Info.FilePath.Add(currentParameter.FilePath); //下载文件 bool success; //提示更换新Part NewPart(i + 1, videos.Length); //下载视频文件 success = Network.DownloadFile(currentParameter, this.Info); //下载视频 try { success = Network.DownloadFile(currentParameter, this.Info); if (!success) //未出现错误即用户手动停止 { return(false); } } catch (Exception ex) //下载文件时出现错误 { //如果此任务由一个视频组成,则报错(下载失败) if (Info.PartCount == 1) { throw; } else //否则继续下载,设置“部分失败”状态 { Info.PartialFinished = true; Info.PartialFinishedDetail += "\r\n文件: " + currentParameter.Url + " 下载失败"; } } } //生成.acplay文件 if (File.Exists(Path.Combine(Info.SaveDirectory.ToString(), Settings["title"] + ".json"))) { var acplay = GenerateAcplayConfig(pr, Settings["title"]); if (!string.IsNullOrEmpty(acplay)) { Settings["AcPlay"] = acplay; } } //下载成功完成 return(true); }