/// <summary> /// 下载弹幕 /// </summary> /// <param name="title">文件名</param> /// <returns>是否下载成功</returns> private bool DownloadSubtitle(string title) { if ((Info.DownloadTypes & DownloadType.Subtitle) != 0) { //设置文件名 var renamehelper = new CustomFileNameHelper(); //----------下载字幕----------- TipText("正在下载字幕文件"); //字幕文件(on)位置 string filename = renamehelper.CombineFileName(Settings["CustomFileName"], title, "", "", "json", Info.Settings["ACNumber"], Info.Settings["ACSubNumber"]); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); //生成父文件夹 if (!Directory.Exists(Path.GetDirectoryName(filename))) { Directory.CreateDirectory(Path.GetDirectoryName(filename)); } Info.SubFilePath.Add(filename); //取得字幕文件(on)地址 string subUrl = @"http://comment.acfun.tv/" + Info.Settings["cid"] + ".json?clientID=0.46080235205590725"; try { //下载字幕文件 string subcontent = Network.GetHtmlSource(subUrl, Encoding.UTF8, Info.Proxy); //保存文件 File.WriteAllText(filename, subcontent); } catch { return(false); } //字幕文件(lock)地址 filename = renamehelper.CombineFileName(Settings["CustomFileName"], title, "", "", "[锁定].json", Info.Settings["ACNumber"], Info.Settings["ACSubNumber"]); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); Info.SubFilePath.Add(filename); //取得字幕文件(lock)地址 subUrl = @"http://comment.acfun.tv/" + Info.Settings["cid"] + "_lock.json?clientID=0.46080235205590725"; try { //下载字幕文件 WebClient wc = new WebClient(); wc.Proxy = Info.Proxy; byte[] data = wc.DownloadData(subUrl); string subcontent = Encoding.UTF8.GetString(data); //保存文件 File.WriteAllText(filename, subcontent); } catch { } } return(true); }
/// <summary> /// 下载弹幕 /// </summary> /// <param name="title">文件名</param> /// <returns>是否下载成功</returns> private bool DownloadComment(string title, string subtitle, string id) { //如果不是“不下载弹幕”且ID不为空 if (((Info.DownloadTypes & DownloadType.Subtitle) != 0) && (!string.IsNullOrEmpty(id))) { //设置文件名 var renamehelper = new CustomFileNameHelper(); //----------下载字幕----------- TipText("正在下载字幕文件"); //字幕文件(on)地址 string filename = renamehelper.CombineFileName(Settings["CustomFileName"], title, subtitle, "", "xml", Settings["AVNumber"], Settings["AVSubNumber"]); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); //生成父文件夹 if (!Directory.Exists(Path.GetDirectoryName(filename))) { Directory.CreateDirectory(Path.GetDirectoryName(filename)); } Info.SubFilePath.Add(filename); //取得字幕文件地址 string subUrl = "http://comment.bilibili.com/" + id + ".xml"; //WorkItem #1410 //下载字幕文件 try { Network.DownloadFile(new DownloadParameter() { Url = subUrl, FilePath = filename, Proxy = Info.Proxy }); } catch { return(false); } } return(true); }
private void DownloadSubtitle(string vid) { if ((Info.DownloadTypes & DownloadType.Subtitle) == 0) { return; } //设置文件名 var renamehelper = new CustomFileNameHelper(); //----------下载字幕----------- TipText("正在下载弹幕文件"); //字幕文件(on)位置 string filename = renamehelper.CombineFileName(m_customFileName, m_videoTitle, m_currentPartTitle, "", "json", m_acNumber, m_acSubNumber); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); //生成父文件夹 if (!Directory.Exists(Path.GetDirectoryName(filename))) { Directory.CreateDirectory(Path.GetDirectoryName(filename)); } Info.SubFilePath.Add(filename); //取得字幕文件(on)地址 string subUrl = @"http://static.comment.acfun.mm111.net/" + vid + "-2500"; try { //下载字幕文件 string commentString = Network.GetHtmlSource(subUrl, Encoding.UTF8, Info.Proxy); commentString = commentString.Replace("],[],[", ",") .Replace("[[,", "[[").Replace("[[", "[").Replace("]]", "]"); //将弹幕修正为以前的格式 //保存文件 System.IO.File.WriteAllText(filename, commentString); } catch { return; } }
/// <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); }
/// <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; }
/// <summary> /// 下载弹幕 /// </summary> /// <param name="title">文件名</param> /// <returns>是否下载成功</returns> private bool DownloadComment(string title, string subtitle, string id) { //如果不是“不下载弹幕”且ID不为空 if (((Info.DownloadTypes & DownloadType.Subtitle) != 0) && (!string.IsNullOrEmpty(id))) { //设置文件名 var renamehelper = new CustomFileNameHelper(); //----------下载字幕----------- TipText("正在下载字幕文件"); //字幕文件(on)地址 string filename = renamehelper.CombineFileName(Settings["CustomFileName"], title, subtitle, "", "xml", Info.Settings["AVNumber"], Info.Settings["AVSubNumber"]); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); //生成父文件夹 if (!Directory.Exists(Path.GetDirectoryName(filename))) Directory.CreateDirectory(Path.GetDirectoryName(filename)); Info.SubFilePath.Add(filename); //取得字幕文件(on)地址 string subUrl = "http://comment.bilibili.tv/dm," + id; //下载字幕文件 try { Network.DownloadFile(new DownloadParameter() { Url = subUrl, FilePath = filename, Proxy = Info.Proxy }); } catch { return false; } } return true; }
/// <summary> /// 生成acplay配置文件 /// </summary> /// <param name="pr">Parser的解析结果</param> /// <param name="title">文件标题</param> private string GenerateAcplayConfig(ParseResult pr, string title) { try { //生成新的配置 AcPlayConfiguration c = new AcPlayConfiguration(); //播放器 c.PlayerName = "acfun"; //播放器地址 c.PlayerUrl = Info.Settings["PlayerUrl"]; //端口 c.HttpServerPort = 7776; c.ProxyServerPort = 7777; //视频 c.Videos = new Video[Info.FilePath.Count]; for (int i = 0; i < Info.FilePath.Count; i++) { c.Videos[i] = new Video(); c.Videos[i].FileName = Path.GetFileName(Info.FilePath[i]); if (pr != null) { if (pr.Items[i].Information.ContainsKey("length")) { c.Videos[i].Length = int.Parse(pr.Items[i].Information["length"]); } } if (pr != null) { if (pr.Items[i].Information.ContainsKey("order")) { c.Videos[i].Order = int.Parse(pr.Items[i].Information["order"]); } } } //弹幕 c.Subtitles = new string[Info.SubFilePath.Count]; for (int i = 0; i < Info.SubFilePath.Count; i++) { c.Subtitles[i] = Path.GetFileName(Info.SubFilePath[i]); } //其他 c.ExtraConfig = new SerializableDictionary <string, string>(); if (pr != null) { if (pr.SpecificResult.ContainsKey("totallength")) //totallength { c.ExtraConfig.Add("totallength", pr.SpecificResult["totallength"]); } } if (pr != null) { if (pr.SpecificResult.ContainsKey("src")) //src { c.ExtraConfig.Add("src", pr.SpecificResult["src"]); } } if (pr != null) { if (pr.SpecificResult.ContainsKey("framecount")) //framecount { c.ExtraConfig.Add("framecount", pr.SpecificResult["framecount"]); } } //配置文件的生成地址 var renamehelper = new CustomFileNameHelper(); string filename = renamehelper.CombineFileName(Settings["CustomFileName"], title, "", "", "acplay", Info.Settings["ACNumber"], Info.Settings["ACSubNumber"]); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); //string path = Path.Combine(Info.SaveDirectory.ToString(), title + ".acplay"); //序列化到文件中 using (var fs = new FileStream(filename, FileMode.Create)) { XmlSerializer s = new XmlSerializer(typeof(AcPlayConfiguration)); s.Serialize(fs, c); } return(filename); } catch { return(""); } }
/// <summary> /// 生成acplay配置文件 /// </summary> /// <param name="pr">Parser的解析结果</param> /// <param name="title">文件标题</param> private string GenerateAcplayConfig(ParseResult pr, string title) { try { //生成新的配置 AcPlayConfiguration c = new AcPlayConfiguration(); //播放器 c.PlayerName = "acfun"; //播放器地址 c.PlayerUrl = Info.Settings["PlayerUrl"]; //端口 c.HttpServerPort = 7776; c.ProxyServerPort = 7777; //视频 c.Videos = new Video[Info.FilePath.Count]; for (int i = 0; i < Info.FilePath.Count; i++) { c.Videos[i] = new Video(); c.Videos[i].FileName = Path.GetFileName(Info.FilePath[i]); if (pr != null) if (pr.Items[i].Information.ContainsKey("length")) c.Videos[i].Length = int.Parse(pr.Items[i].Information["length"]); if (pr != null) if (pr.Items[i].Information.ContainsKey("order")) c.Videos[i].Order = int.Parse(pr.Items[i].Information["order"]); } //弹幕 c.Subtitles = new string[Info.SubFilePath.Count]; for (int i = 0; i < Info.SubFilePath.Count; i++) { c.Subtitles[i] = Path.GetFileName(Info.SubFilePath[i]); } //其他 c.ExtraConfig = new SerializableDictionary<string, string>(); if (pr != null) if (pr.SpecificResult.ContainsKey("totallength")) //totallength c.ExtraConfig.Add("totallength", pr.SpecificResult["totallength"]); if (pr != null) if (pr.SpecificResult.ContainsKey("src")) //src c.ExtraConfig.Add("src", pr.SpecificResult["src"]); if (pr != null) if (pr.SpecificResult.ContainsKey("framecount")) //framecount c.ExtraConfig.Add("framecount", pr.SpecificResult["framecount"]); //配置文件的生成地址 var renamehelper = new CustomFileNameHelper(); string filename = renamehelper.CombineFileName(Settings["CustomFileName"], title, "", "", "acplay", Info.Settings["ACNumber"], Info.Settings["ACSubNumber"]); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); //string path = Path.Combine(Info.SaveDirectory.ToString(), title + ".acplay"); //序列化到文件中 using (var fs = new FileStream(filename, FileMode.Create)) { XmlSerializer s = new XmlSerializer(typeof(AcPlayConfiguration)); s.Serialize(fs, c); } return filename; } catch { return ""; } }
/// <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 override bool Download() { //开始下载 TipText("正在分析视频地址"); //修正井号 Info.Url = Info.Url.TrimEnd('#'); //修正旧版URL Info.Url = Info.Url.Replace("bilibili.us", "bilibili.tv"); Info.Url = Info.Url.Replace("www.bilibili.tv", "bilibili.kankanews.com"); Info.Url = Info.Url.Replace("bilibili.tv", "bilibili.kankanews.com"); //修正简写URL if (Regex.Match(Info.Url, @"^av\d{2,6}$").Success) Info.Url = "http://bilibili.kankanews.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; //取得AV号和子编号 Match mAVNumber = Regex.Match(Info.Url, @"(?<av>av\d+)/index_(?<sub>\d+)\.html"); Settings["AVNumber"] = mAVNumber.Groups["ac"].Value; Settings["AVSubNumber"] = mAVNumber.Groups["sub"].Value; //设置自定义文件名 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 == "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(); string subtitle = title; //取得子标题 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; } } //如果需要解析关联下载项 //解析关联项需要同时满足的条件: //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 + " - " + subtitle; //过滤非法字符 title = Tools.InvalidCharacterFilter(title, ""); subtitle = Tools.InvalidCharacterFilter(subtitle, ""); //清空地址 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; //下载弹幕 bool comment = DownloadComment(title, subtitle, id); if (!comment) { Info.PartialFinished = true; Info.PartialFinishedDetail += "\r\n弹幕文件文件下载失败"; } //解析器的解析结果 ParseResult pr = null; //如果允许下载视频 if ((Info.DownloadTypes & DownloadType.Video) != 0) { 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"; //设置文件名 var renamehelper = new CustomFileNameHelper(); string filename = renamehelper.CombineFileName(Settings["CustomFileName"], title, subtitle, Info.PartCount == 1 ? "" : Info.CurrentPart.ToString(), ext.Replace(".", ""), Info.Settings["AVNumber"], Info.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 (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, subtitle); //支持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) { Info.Settings["user"] = ""; Info.Settings["password"] = ""; throw ex; } return true; }
/// <summary> /// 下载弹幕 /// </summary> /// <param name="title">文件名</param> /// <returns>是否下载成功</returns> private bool DownloadSubtitle(string title) { if ((Info.DownloadTypes & DownloadType.Subtitle)!= 0) { //设置文件名 var renamehelper = new CustomFileNameHelper(); //----------下载字幕----------- TipText("正在下载字幕文件"); //字幕文件(on)位置 string filename = renamehelper.CombineFileName(Settings["CustomFileName"], title, "", "", "json", Info.Settings["ACNumber"], Info.Settings["ACSubNumber"]); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); //生成父文件夹 if (!Directory.Exists(Path.GetDirectoryName(filename))) Directory.CreateDirectory(Path.GetDirectoryName(filename)); Info.SubFilePath.Add(filename); //取得字幕文件(on)地址 string subUrl = @"http://comment.acfun.tv/" + Info.Settings["cid"] + ".json?clientID=0.46080235205590725"; try { //下载字幕文件 string subcontent = Network.GetHtmlSource(subUrl, Encoding.UTF8, Info.Proxy); //保存文件 File.WriteAllText(filename, subcontent); } catch { return false; } //字幕文件(lock)地址 filename = renamehelper.CombineFileName(Settings["CustomFileName"], title, "", "", "[锁定].json", Info.Settings["ACNumber"], Info.Settings["ACSubNumber"]); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); Info.SubFilePath.Add(filename); //取得字幕文件(lock)地址 subUrl = @"http://comment.acfun.tv/" + Info.Settings["cid"] + "_lock.json?clientID=0.46080235205590725"; try { //下载字幕文件 WebClient wc = new WebClient(); wc.Proxy = Info.Proxy; byte[] data = wc.DownloadData(subUrl); string subcontent = Encoding.UTF8.GetString(data); //保存文件 File.WriteAllText(filename, subcontent); } catch { } } 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); }
/// <summary> /// 下载弹幕 /// </summary> /// <param name="title">文件名</param> /// <returns>是否下载成功</returns> private void DownloadSubtitle() { if ((Info.DownloadTypes & DownloadType.Subtitle) != 0) { //设置文件名 var renamehelper = new CustomFileNameHelper(); //----------下载字幕----------- TipText("正在下载弹幕文件"); //字幕文件(on)位置 string filename = renamehelper.CombineFileName(m_customFileName, m_videoTitle, m_currentPartTitle, "", "json", m_acNumber, m_acSubNumber); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); //生成父文件夹 if (!Directory.Exists(Path.GetDirectoryName(filename))) { Directory.CreateDirectory(Path.GetDirectoryName(filename)); } Info.SubFilePath.Add(filename); //取得字幕文件(on)地址 string subUrl = @"http://comment.acfun.tv/" + m_danmakuId + ".json?clientID=0.47080235205590725"; try { //下载字幕文件 string subcontent = Network.GetHtmlSource(subUrl, Encoding.UTF8, Info.Proxy); //保存文件 System.IO.File.WriteAllText(filename, subcontent); } catch { return; } //字幕文件(lock)地址 filename = renamehelper.CombineFileName(m_customFileName, m_videoTitle, m_currentPartTitle, "", "[锁定].json", m_acNumber, m_acSubNumber); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); //取得字幕文件(lock)地址 subUrl = @"http://comment.acfun.tv/" + m_danmakuId + "_lock.json?clientID=0.47080235205590725"; try { //下载字幕文件 WebClient wc = new WebClient(); wc.Proxy = Info.Proxy; byte[] data = wc.DownloadData(subUrl); string subcontent = Encoding.UTF8.GetString(data); //检测【锁定】弹幕文件是否是正确的JSON格式 if (subcontent.StartsWith("[{")) { Info.SubFilePath.Add(filename); //保存文件 System.IO.File.WriteAllText(filename, subcontent); } } catch { } } return; }
//下载视频 public override bool Download() { //开始下载 TipText("正在分析视频地址"); //修正井号 Info.Url = Info.Url.TrimEnd('#'); //修正旧版URL Info.Url = Info.Url.Replace("bilibili.us", "bilibili.tv"); Info.Url = Info.Url.Replace("www.bilibili.tv", "bilibili.kankanews.com"); Info.Url = Info.Url.Replace("bilibili.tv", "bilibili.kankanews.com"); //修正简写URL if (Regex.Match(Info.Url, @"^av\d{2,6}$").Success) { Info.Url = "http://bilibili.kankanews.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; //取得AV号和子编号 Match mAVNumber = Regex.Match(Info.Url, @"(?<av>av\d+)/index_(?<sub>\d+)\.html"); Settings["AVNumber"] = mAVNumber.Groups["ac"].Value; Settings["AVSubNumber"] = mAVNumber.Groups["sub"].Value; //设置自定义文件名 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 == "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(); string subtitle = title; //取得子标题 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; } } //如果需要解析关联下载项 //解析关联项需要同时满足的条件: //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 + " - " + subtitle; //过滤非法字符 title = Tools.InvalidCharacterFilter(title, ""); subtitle = Tools.InvalidCharacterFilter(subtitle, ""); //清空地址 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; //下载弹幕 bool comment = DownloadComment(title, subtitle, id); if (!comment) { Info.PartialFinished = true; Info.PartialFinishedDetail += "\r\n弹幕文件文件下载失败"; } //解析器的解析结果 ParseResult pr = null; //如果允许下载视频 if ((Info.DownloadTypes & DownloadType.Video) != 0) { 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"; } //设置文件名 var renamehelper = new CustomFileNameHelper(); string filename = renamehelper.CombineFileName(Settings["CustomFileName"], title, subtitle, Info.PartCount == 1 ? "" : Info.CurrentPart.ToString(), ext.Replace(".", ""), Info.Settings["AVNumber"], Info.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 (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, subtitle); //支持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) { Info.Settings["user"] = ""; Info.Settings["password"] = ""; throw ex; } return(true); }
/// <summary> /// 生成acplay配置文件 /// </summary> /// <param name="pr">Parser的解析结果</param> /// <param name="title">文件标题</param> private string GenerateAcplayConfig(ParseResult pr) { if (Tools.IsRunningOnMono) return ""; try { //生成新的配置 var c = new AcPlayConfiguration { PlayerName = "acfun", PlayerUrl = Info.Settings["PlayerUrl"], HttpServerPort = 7776, ProxyServerPort = 7777, Videos = new Video[Info.FilePath.Count], WebUrl = Info.Url }; for (int i = 0; i < Info.FilePath.Count; i++) { c.Videos[i] = new Video(); c.Videos[i].FileName = Path.GetFileName(Info.FilePath[i]); if (pr != null) if (pr.Items[i].Information.ContainsKey("length")) c.Videos[i].Length = int.Parse(pr.Items[i].Information["length"]); if (pr != null) if (pr.Items[i].Information.ContainsKey("order")) c.Videos[i].Order = int.Parse(pr.Items[i].Information["order"]); } //弹幕 c.Subtitles = new string[Info.SubFilePath.Count]; for (int i = 0; i < Info.SubFilePath.Count; i++) { c.Subtitles[i] = Path.GetFileName(Info.SubFilePath[i]); } //其他 c.ExtraConfig = new SerializableDictionary<string, string>(); if (pr != null) if (pr.SpecificResult.ContainsKey("totallength")) //totallength c.ExtraConfig.Add("totallength", pr.SpecificResult["totallength"]); if (pr != null) if (pr.SpecificResult.ContainsKey("src")) //src c.ExtraConfig.Add("src", pr.SpecificResult["src"]); if (pr != null) if (pr.SpecificResult.ContainsKey("framecount")) //framecount c.ExtraConfig.Add("framecount", pr.SpecificResult["framecount"]); //配置文件的生成地址 var renamehelper = new CustomFileNameHelper(); string filename = renamehelper.CombineFileName(m_customFileName, m_videoTitle, m_currentPartTitle, "", "acplay", m_acNumber, m_acSubNumber); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); Info.FilePath.Add(filename); //string path = Path.Combine(Info.SaveDirectory.ToString(), title + ".acplay"); //序列化到文件中 using (var fs = new FileStream(filename, FileMode.Create)) { var s = new XmlSerializer(typeof (AcPlayConfiguration)); s.Serialize(fs, c); } return filename; } catch { return ""; } }
/// <summary> /// 下载弹幕 /// </summary> /// <param name="title">文件名</param> /// <returns>是否下载成功</returns> private void DownloadSubtitle() { if ((Info.DownloadTypes & DownloadType.Subtitle) != 0) { //设置文件名 var renamehelper = new CustomFileNameHelper(); //----------下载字幕----------- TipText("正在下载弹幕文件"); //字幕文件(on)位置 string filename = renamehelper.CombineFileName(m_customFileName, m_videoTitle, m_currentPartTitle, "", "json", m_acNumber, m_acSubNumber); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); //生成父文件夹 if (!Directory.Exists(Path.GetDirectoryName(filename))) Directory.CreateDirectory(Path.GetDirectoryName(filename)); Info.SubFilePath.Add(filename); //取得字幕文件(on)地址 string subUrl = @"http://comment.acfun.tv/" + m_danmakuId + ".json?clientID=0.47080235205590725"; try { //下载字幕文件 string subcontent = Network.GetHtmlSource(subUrl, Encoding.UTF8, Info.Proxy); //保存文件 System.IO.File.WriteAllText(filename, subcontent); } catch { return; } //字幕文件(lock)地址 filename = renamehelper.CombineFileName(m_customFileName, m_videoTitle, m_currentPartTitle, "", "[锁定].json", m_acNumber, m_acSubNumber); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); //取得字幕文件(lock)地址 subUrl = @"http://comment.acfun.tv/" + m_danmakuId + "_lock.json?clientID=0.47080235205590725"; try { //下载字幕文件 WebClient wc = new WebClient(); wc.Proxy = Info.Proxy; byte[] data = wc.DownloadData(subUrl); string subcontent = Encoding.UTF8.GetString(data); //检测【锁定】弹幕文件是否是正确的JSON格式 if (subcontent.StartsWith("[{")) { Info.SubFilePath.Add(filename); //保存文件 System.IO.File.WriteAllText(filename, subcontent); } } catch { } } return; }
private void DownloadSubtitle(string vid) { if ((Info.DownloadTypes & DownloadType.Subtitle) == 0) return; //设置文件名 var renamehelper = new CustomFileNameHelper(); //----------下载字幕----------- TipText("正在下载弹幕文件"); //字幕文件(on)位置 string filename = renamehelper.CombineFileName(m_customFileName, m_videoTitle, m_currentPartTitle, "", "json", m_acNumber, m_acSubNumber); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); //生成父文件夹 if (!Directory.Exists(Path.GetDirectoryName(filename))) Directory.CreateDirectory(Path.GetDirectoryName(filename)); Info.SubFilePath.Add(filename); //取得字幕文件(on)地址 string subUrl = @"http://static.comment.acfun.mm111.net/" + vid + "-2500"; try { //下载字幕文件 string commentString = Network.GetHtmlSource(subUrl, Encoding.UTF8, Info.Proxy); commentString = commentString.Replace("],[],[", ",") .Replace("[[,", "[[").Replace("[[", "[").Replace("]]", "]"); //将弹幕修正为以前的格式 //保存文件 System.IO.File.WriteAllText(filename, commentString); } catch { return; } }
/// <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; }
/// <summary> /// 生成acplay配置文件 /// </summary> /// <param name="pr">Parser的解析结果</param> /// <param name="title">文件标题</param> private string GenerateAcplayConfig(ParseResult pr) { if (Tools.IsRunningOnMono) { return(""); } try { //生成新的配置 var c = new AcPlayConfiguration { PlayerName = "acfun", PlayerUrl = Info.Settings["PlayerUrl"], HttpServerPort = 7776, ProxyServerPort = 7777, Videos = new Video[Info.FilePath.Count], WebUrl = Info.Url }; for (int i = 0; i < Info.FilePath.Count; i++) { c.Videos[i] = new Video(); c.Videos[i].FileName = Path.GetFileName(Info.FilePath[i]); if (pr != null) { if (pr.Items[i].Information.ContainsKey("length")) { c.Videos[i].Length = int.Parse(pr.Items[i].Information["length"]); } } if (pr != null) { if (pr.Items[i].Information.ContainsKey("order")) { c.Videos[i].Order = int.Parse(pr.Items[i].Information["order"]); } } } //弹幕 c.Subtitles = new string[Info.SubFilePath.Count]; for (int i = 0; i < Info.SubFilePath.Count; i++) { c.Subtitles[i] = Path.GetFileName(Info.SubFilePath[i]); } //其他 c.ExtraConfig = new SerializableDictionary <string, string>(); if (pr != null) { if (pr.SpecificResult.ContainsKey("totallength")) //totallength { c.ExtraConfig.Add("totallength", pr.SpecificResult["totallength"]); } } if (pr != null) { if (pr.SpecificResult.ContainsKey("src")) //src { c.ExtraConfig.Add("src", pr.SpecificResult["src"]); } } if (pr != null) { if (pr.SpecificResult.ContainsKey("framecount")) //framecount { c.ExtraConfig.Add("framecount", pr.SpecificResult["framecount"]); } } //配置文件的生成地址 var renamehelper = new CustomFileNameHelper(); string filename = renamehelper.CombineFileName(m_customFileName, m_videoTitle, m_currentPartTitle, "", "acplay", m_acNumber, m_acSubNumber); filename = Path.Combine(Info.SaveDirectory.ToString(), filename); Info.FilePath.Add(filename); //string path = Path.Combine(Info.SaveDirectory.ToString(), title + ".acplay"); //序列化到文件中 using (var fs = new FileStream(filename, FileMode.Create)) { var s = new XmlSerializer(typeof(AcPlayConfiguration)); s.Serialize(fs, c); } return(filename); } catch { return(""); } }
/// <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; }