/// <summary> /// 解析任意视频源地址 /// </summary> public ParseResult Parse(ParseRequest request) { //返回值 ParseResult pr = new ParseResult(); //分辨率 string resolution = request.SpecificConfiguration.ContainsKey("resolution") ? request.SpecificConfiguration["resolution"] : ""; //修正url string url = "http://www.flvcd.com/parse.php?kw=" + Tools.UrlEncode(request.Id) + resolution; //取得网页源文件 string src = Network.GetHtmlSource(url, Encoding.GetEncoding("GB2312"), request.Proxy); //检查是否需要密码 if (src.Contains("请输入密码")) { url = url + "&passwd=" + request.Password; src = Network.GetHtmlSource(url, Encoding.GetEncoding("GB2312"), request.Proxy); } //取得内容 Regex rContent = new Regex("<input type=\"hidden\" name=\"inf\".+\">", RegexOptions.Singleline); Match mContent = rContent.Match(src); string content = mContent.Value; //取得各Part下载地址 List<string> partUrls = new List<string>(); Regex rPartUrls = new Regex(@"<U>(?<url>.+)"); MatchCollection mcPartUrls = rPartUrls.Matches(content); foreach (Match item in mcPartUrls) { pr.Items.Add(new ParseResultItem() { RealAddress = item.Groups["url"].Value }); } return pr; }
/// <summary> /// 解析任意视频源地址 /// </summary> public ParseResult Parse(ParseRequest request) { //返回值 ParseResult pr = new ParseResult(); //分辨率 string resolution = request.SpecificConfiguration.ContainsKey("resolution") ? request.SpecificConfiguration["resolution"] : ""; //修正url string url = "http://www.flvcd.com/parse.php?kw=" + Tools.UrlEncode(request.Id) + resolution; //取得网页源文件 string src = Network.GetHtmlSource(url, Encoding.GetEncoding("GB2312"), request.Proxy); //检查是否需要密码 if (src.Contains("请输入密码")) { url = url + "&passwd=" + request.Password; src = Network.GetHtmlSource(url, Encoding.GetEncoding("GB2312"), request.Proxy); } var urlMatch = Regex.Match(src, @"<input type=#hidden# name=#inf# value=#(?<urls>.+?)#".Replace('#', '"')); string content = urlMatch.Groups["urls"].Value; List<string> partUrls = new List<string>(content.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)); foreach (string partUrl in partUrls) { pr.Items.Add(new ParseResultItem() { RealAddress = partUrl }); } return pr; }
/// <summary> /// 通过Bilibili接口解析视频文件源地址 /// </summary> public ParseResult Parse(ParseRequest request) { ParseResult pr = new ParseResult(); //合并完整url //这里使用标准方法调用Bilibili API var ts = Convert.ToInt64((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0)).TotalMilliseconds); string url = string.Format(@"http://interface.bilibili.com/playurl?appkey={0}&cid={1}&ts={2}&sign={3}", BilibiliPlugin.AppKey, request.Id, ts, Tools.GetStringHash("appkey=" + BilibiliPlugin.AppKey + "&cid=" + request.Id + "&ts=" + ts + BilibiliPlugin.AppSecret)); var httpRequest = (HttpWebRequest)WebRequest.Create(url); httpRequest.Proxy = request.Proxy; httpRequest.CookieContainer = request.CookieContainer; string source = Network.GetHtmlSource(httpRequest, Encoding.UTF8); Video videoInfo; var serializer = new XmlSerializer(typeof(Video)); using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(source))) { videoInfo = (Video) serializer.Deserialize(ms); } //视频总长度 var totallength = videoInfo.Timelength; if (totallength != null) pr.SpecificResult.Add("totallength", totallength); //src var src = videoInfo.Src; if (src != null) pr.SpecificResult.Add("src", src); //视频信息 foreach (var durl in videoInfo.Durl) { var pri = new ParseResultItem() { RealAddress = durl.Url }; pri.Information.Add("order", durl.Order); pri.Information.Add("length", durl.Length); pr.Items.Add(pri); } //返回结果 return pr; }
/// <summary> /// 解析新浪视频视频文件源地址 /// </summary> public ParseResult Parse(ParseRequest request) { ParseResult pr = new ParseResult(); /* * 参数 解释 * vid 和以前的vid一样 * ran 生成的一个随机数 * p 值为i,意义不明 * k 16+N长度的hash值 * * 把这个算法拿出去用的都要打PP! */ //var ran = new Random(Environment.TickCount).Next(0, 1000); //var key = WhereIsTheKey(request.Id, "0", ran); var key = GenerateKey(request.Id + "footstone"); //合并完整url //string url = @"http://v.iask.com/v_play.php?vid=" + request.Id + "&ran=" + ran + "&p=i&k=" + key; string url = @"http://2dland.vipsinaapp.com/video.php?action=xml&type=xina&vid="+request.Id+"&key=" + key; string source = Network.GetHtmlSource(url, Encoding.UTF8, request.Proxy); //视频总长度 string totallength = Regex.Match(source, @"<timelength>(?<timelength>\d+)</timelength>").Groups["timelength"].Value; //Framecount string framecount = Regex.Match(source, @"<framecount>(?<framecount>\d+)</framecount>").Groups["framecount"].Value; //src string src = Regex.Match(source, @"<src>(?<src>\d+)</src>").Groups["src"].Value; pr.SpecificResult.Add("totallength", totallength); pr.SpecificResult.Add("framecount", framecount); pr.SpecificResult.Add("src", src); //vstr string vstr = Regex.Match(source, @"(?<=<vstr><!\[CDATA\[)\w+").Value; //视频信息 Regex r = new Regex(@"<durl>.+?<order>(?<order>\d+)</order>.+?<length>(?<length>\d+)</length>.+?<url><!\[CDATA\[(?<url>.+?)\]\]></url>.+?</durl>", RegexOptions.Singleline); MatchCollection matches = r.Matches(source); foreach (Match item in matches) { var pri = new ParseResultItem(); pri.RealAddress = item.Groups["url"].Value; pri.Information.Add("order", item.Groups["order"].Value); pri.Information.Add("length", item.Groups["length"].Value); pr.Items.Add(pri); } //返回结果 return pr; }
public ParseResult Parse(ParseRequest request) { var httpRequest =(HttpWebRequest) WebRequest.Create(@"http://jiexi.acfun.info/index.php?type=mobileclient&vid=" + request.Id); httpRequest.Proxy = request.Proxy; httpRequest.UserAgent = "Dalvik/1.6.0 (Linux; U; Android 4.2.2; H30-U10 Build/HuaweiH30-U10)"; httpRequest.Accept = "application/json"; httpRequest.Headers.Add("Accept-Encoding", "gzip"); var json = Network.GetHtmlSource(httpRequest, Encoding.UTF8); var acInfo = JsonConvert.DeserializeObject<AcInfo>(json); if (acInfo.code != 200) { throw new Exception("AcfunInterfaceParser: " + acInfo.message); } var pr = new ParseResult(); var qualityDict = new Dictionary<string, string>(); AddQualityDict(qualityDict, acInfo.result); string chosenQuality = ToolForm.CreateSingleSelectForm("请选择视频清晰度:", qualityDict, "", request.AutoAnswers, "acfun"); var videoInfo = GetVideoInfoFromQuality(acInfo, chosenQuality); //视频总长度 pr.SpecificResult.Add("totallength", videoInfo.totalseconds.ToString()); //Framecount pr.SpecificResult.Add("framecount", "0"); //src pr.SpecificResult.Add("src", "200"); //vstr pr.SpecificResult.Add("vstr", ""); videoInfo.files.ForEach(file => { pr.Items.Add(new ParseResultItem { RealAddress = file.url, Information = new SerializableDictionary<string, string>() { {"length", (file.seconds*1000).ToString()}, {"order", file.no.ToString()} } }); }); return pr; }
/// <summary> /// 解析新浪视频视频文件源地址 /// </summary> public ParseResult Parse(ParseRequest request) { ParseResult pr = new ParseResult(); //合并完整url string url = @"http://v.iask.com/v_play.php?vid=" + request.Id; string source = Network.GetHtmlSource(url, Encoding.UTF8, request.Proxy); //视频总长度 string totallength = Regex.Match(source, @"<timelength>(?<timelength>\d+)</timelength>").Groups["timelength"].Value; //Framecount string framecount = Regex.Match(source, @"<framecount>(?<framecount>\d+)</framecount>").Groups["framecount"].Value; //src string src = Regex.Match(source, @"<src>(?<src>\d+)</src>").Groups["src"].Value; pr.SpecificResult.Add("totallength", totallength); pr.SpecificResult.Add("framecount", framecount); pr.SpecificResult.Add("src", src); //vstr string vstr = Regex.Match(source, @"(?<=<vstr><!\[CDATA\[)\w+").Value; //视频信息 Regex r = new Regex(@"<durl>.+?<order>(?<order>\d+)</order>.+?<length>(?<length>\d+)</length>.+?<url><!\[CDATA\[(?<url>.+?)\]\]></url>.+?</durl>", RegexOptions.Singleline); MatchCollection matches = r.Matches(source); foreach (Match item in matches) { var pri = new ParseResultItem(); string real = item.Groups["url"].Value; if (real.EndsWith(".flv", StringComparison.CurrentCultureIgnoreCase) || real.EndsWith(".hlv", StringComparison.CurrentCultureIgnoreCase) || real.EndsWith(".mp4", StringComparison.CurrentCultureIgnoreCase)) { if (!string.IsNullOrEmpty(vstr)) { //real = real +"?vstr=" + vstr; } } pri.RealAddress = real; pri.Information.Add("order", item.Groups["order"].Value); pri.Information.Add("length", item.Groups["length"].Value); pr.Items.Add(pri); } //返回结果 return(pr); }
/// <summary> /// 解析新浪视频视频文件源地址 /// </summary> public ParseResult Parse(ParseRequest request) { ParseResult pr = new ParseResult(); //合并完整url string url = @"http://v.iask.com/v_play.php?vid=" + request.Id; string source = Network.GetHtmlSource(url, Encoding.UTF8, request.Proxy); //视频总长度 string totallength = Regex.Match(source, @"<timelength>(?<timelength>\d+)</timelength>").Groups["timelength"].Value; //Framecount string framecount = Regex.Match(source, @"<framecount>(?<framecount>\d+)</framecount>").Groups["framecount"].Value; //src string src = Regex.Match(source, @"<src>(?<src>\d+)</src>").Groups["src"].Value; pr.SpecificResult.Add("totallength", totallength); pr.SpecificResult.Add("framecount", framecount); pr.SpecificResult.Add("src", src); //vstr string vstr = Regex.Match(source, @"(?<=<vstr><!\[CDATA\[)\w+").Value; //视频信息 Regex r = new Regex(@"<durl>.+?<order>(?<order>\d+)</order>.+?<length>(?<length>\d+)</length>.+?<url><!\[CDATA\[(?<url>.+?)\]\]></url>.+?</durl>", RegexOptions.Singleline); MatchCollection matches = r.Matches(source); foreach (Match item in matches) { var pri = new ParseResultItem(); string real = item.Groups["url"].Value; if (real.EndsWith(".flv", StringComparison.CurrentCultureIgnoreCase) || real.EndsWith(".hlv", StringComparison.CurrentCultureIgnoreCase) || real.EndsWith(".mp4", StringComparison.CurrentCultureIgnoreCase)) { if (!string.IsNullOrEmpty(vstr)) { //real = real +"?vstr=" + vstr; } } pri.RealAddress = real; pri.Information.Add("order", item.Groups["order"].Value); pri.Information.Add("length", item.Groups["length"].Value); pr.Items.Add(pri); } //返回结果 return pr; }
/// <summary> /// 解析QQ视频源地址 /// </summary> public ParseResult Parse(ParseRequest request) { ParseResult pr = new ParseResult(); //完整url string url = @"http://vv.video.qq.com/geturl?ran=0.16436194255948067&otype=xml&vid=%ID%&platform=1&format=2".Replace(@"%ID%", request.Id); string xmldoc = Network.GetHtmlSource(url, Encoding.UTF8, request.Proxy); Regex r = new Regex(@"\<url\>(?<url>.*?)\</url\>"); MatchCollection mc = r.Matches(xmldoc); if (mc.Count != 0) { foreach (Match item in mc) { pr.Items.Add(new ParseResultItem() { RealAddress = item.Groups[@"url"].Value }); } return pr; } else { pr.Items.Add(new ParseResultItem() { RealAddress = @"http://web.qqvideo.tc.qq.com/" + request.Id + ".flv" }); return pr; } }
/// <summary> /// 解析任意视频源地址 /// </summary> public ParseResult Parse(ParseRequest request) { //返回值 ParseResult pr = new ParseResult(); //分辨率 string resolution = request.SpecificConfiguration.ContainsKey("resolution") ? request.SpecificConfiguration["resolution"] : ""; //修正url string url = "http://www.flvcd.com/parse.php?kw=" + Tools.UrlEncode(request.Id) + resolution; //取得网页源文件 string src = Network.GetHtmlSource(url, Encoding.GetEncoding("GB2312"), request.Proxy); //检查是否需要密码 if (src.Contains("请输入密码")) { url = url + "&passwd=" + request.Password; src = Network.GetHtmlSource(url, Encoding.GetEncoding("GB2312"), request.Proxy); } //取得内容 Regex rContent = new Regex("<input type=\"hidden\" name=\"inf\".+\">", RegexOptions.Singleline); Match mContent = rContent.Match(src); string content = mContent.Value; //取得各Part下载地址 List <string> partUrls = new List <string>(); Regex rPartUrls = new Regex(@"<U>(?<url>.+)"); MatchCollection mcPartUrls = rPartUrls.Matches(content); foreach (Match item in mcPartUrls) { pr.Items.Add(new ParseResultItem() { RealAddress = item.Groups["url"].Value }); } return(pr); }
/// <summary> /// 解析优酷视频源文件地址 /// </summary> ///<remarks>自动应答会检查前缀为<i>youku</i>的所有设置</remarks> public ParseResult Parse(ParseRequest request) { ParseResult pr = new ParseResult(); string urlpre = @"http://v.youku.com/player/getPlayList/VideoIDS/%ID%/timezone/+08/version/5/source/video?n=3&ran=4656&password=%PW%"; string url = urlpre.Replace(@"%ID%", request.Id).Replace(@"%PW%", request.Password); string xmldoc = Network.GetHtmlSource(url, Encoding.UTF8, request.Proxy); //选择语言 Regex rLang = new Regex(@"(?<=""audiolang"":\[).+?(?=\])"); Match mLang = rLang.Match(xmldoc); if (mLang.Success) //如果存在多种语言 { string langs = mLang.Value; Regex rLanguage = new Regex(@"""lang"":""(?<lang>.+?)"",""vid"":""(?<vid>.+?)"""); MatchCollection mcLanguages = rLanguage.Matches(langs); Dictionary <string, string> langDict = new Dictionary <string, string>(); foreach (Match mLanguage in mcLanguages) { langDict.Add(mLanguage.Groups["vid"].Value, Tools.ReplaceUnicode2Str(mLanguage.Groups["lang"].Value)); } string chosenId = ToolForm.CreateSingleSelectForm("您正在下载的视频有多种语言版本,请选择语言:", langDict, "", request.AutoAnswers, "youku"); request.Id = chosenId; url = urlpre.Replace(@"%ID%", request.Id).Replace(@"%PW%", request.Password); xmldoc = Network.GetHtmlSource(url, Encoding.UTF8, request.Proxy); } //正则表达式提取各个参数 string regexstring = "\"seed\":(?<seed>\\w+),.+\"key1\":\"(?<key1>\\w+)\",\"key2\":\"(?<key2>\\w+)\".+\"streamfileids\":{\"(?<fileposfix>\\w+)\":\"(?<fileID>[0-9\\*]+)"; Regex r = new Regex(regexstring); Match m = r.Match(xmldoc); //提取参数 double seed = Double.Parse(m.Groups["seed"].Value); string key1 = m.Groups["key1"].Value; string key2 = m.Groups["key2"].Value; //提取各视频参数 Regex rStreamFileIds = new Regex(@"""streamfileids"":{(?<fileids>.+?)}"); Match mStreamFileIds = rStreamFileIds.Match(xmldoc); string fileIds = mStreamFileIds.Groups["fileids"].Value; var dict = new Dictionary <string, string>(); string defaultres = ""; //是否有超清模式 if (fileIds.Contains("hd2")) { dict.Add("hd2", "超清(hd2)"); defaultres = "hd2"; } //是否有高清模式 if (fileIds.Contains("mp4")) { dict.Add("mp4", "高清(mp4)"); defaultres = "mp4"; } //是否有普通清晰度 if (fileIds.Contains("flv")) { dict.Add("flv", "标清(flv)"); defaultres = "flv"; } string fileposfix = null; string strSelect = null; //自动应答 if (request.AutoAnswers != null && request.AutoAnswers.Count > 0) { foreach (var item in request.AutoAnswers) { if (item.Prefix == "youku") { if (fileIds.Contains(item.Identify)) { strSelect = item.Identify; fileposfix = item.Identify; break; } } } } if (string.IsNullOrEmpty(fileposfix)) { //如果多余一种清晰度 if (dict.Count > 1) { fileposfix = ToolForm.CreateSingleSelectForm("您正在下载优酷视频,请选择视频清晰度:", dict, defaultres, request.AutoAnswers, "youku"); } else { fileposfix = defaultres; } strSelect = fileposfix; } //修正高清 if (fileposfix == "hd2") { fileposfix = "flv"; } //取得FileID Regex rFileID = new Regex(@"""" + strSelect + @""":""(?<fileid>.+?)"""); Match mFileID = rFileID.Match(fileIds); string fileID = mFileID.Groups["fileid"].Value; //提取视频个数 int flv_no = 0; string regexFlvNo = @"""segs"":{""\w+"":\[(?<content>.+?)\]"; Regex rn = new Regex(regexFlvNo); Match mn = rn.Match(xmldoc); char[] tmp_content = mn.Groups["content"].Value.ToCharArray(); foreach (char item in tmp_content) { if (item == '{') { flv_no++; } } //提取key Regex rSegs = new Regex(@"segs"":{(?<segs>.+?)},""streamsizes"); Match mSegs = rSegs.Match(xmldoc); string segs = mSegs.Groups["segs"].Value; Regex rSegsSub = new Regex(@"""" + strSelect + @""":\[(?<segssub>.+?)\]"); Match mSegsSub = rSegsSub.Match(segs); string segssub = mSegsSub.Groups["segssub"].Value; string regexKey = @"""k"":""(?<k>\w+)"",""k2"":""(?<k2>\w+)"""; MatchCollection mcKey = Regex.Matches(segssub, regexKey); List <string> keys = new List <string>(); foreach (Match mKey in mcKey) { keys.Add("?K=" + mKey.Groups["k"].Value + ",k2:" + mKey.Groups["k2"].Value); } //生成sid string sid = genSid(); //生成fileid string fileid = getFileID(fileID, seed); //生成key //string key = genKey(key1, key2); //添加各个地址 List <string> lst = new List <string>(); for (int i = 0; i < keys.Count; i++) { //得到地址 string u = "http://f.youku.com/player/getFlvPath/sid/" + sid + "_" + string.Format("{0:D2}", i) + //"/st/" + fileposfix + "/fileid/" + fileid.Substring(0, 8) + string.Format("{0:D2}", i) "/st/" + fileposfix + "/fileid/" + fileid.Substring(0, 8) + string.Format("{0:X2}", i) + fileid.Substring(10) + keys[i]; //添加地址 pr.Items.Add(new ParseResultItem(u)); } //提取各项详细信息 MatchCollection mcSegs = Regex.Matches(segssub, @"{.+?}"); for (int i = 0; i < mcSegs.Count; i++) { MatchCollection mcKeys = Regex.Matches(mcSegs[i].Value, @"""(?<key>\w+)"":""(?<value>\w+)"""); foreach (Match mkey in mcKeys) { string k = mkey.Groups["key"].Value; string v = mkey.Groups["value"].Value; //修正length和order if (k.Equals("seconds")) { k = "length"; v = (Int32.Parse(v) * 1000).ToString(); } if (k.Equals("no")) { k = "order"; } pr.Items[i].Information.Add(k, v); } } return(pr); }
/// <summary> /// 解析土豆视频 /// </summary> /// <remarks>接受的AutoAnswer对象需要以<i>tudou</i>作为前缀</remarks> public ParseResult Parse(ParseRequest request) { ParseResult pr = new ParseResult(); int t; if(!int.TryParse(request.Id,out t)) //测试iid是否是真实的(应该为数字) { //取得土豆网页面源代码 string tudousource = Network.GetHtmlSource("http://www.tudou.com/programs/view/" + request.Id + "/", Encoding.GetEncoding("GB2312"), request.Proxy); //取得iid列表 Regex rIid = new Regex(@"(?<=iid(:| = ))\d+", RegexOptions.Singleline); MatchCollection mIids = rIid.Matches(tudousource); List<string> iids = new List<string>(); foreach (Match mIid in mIids) { iids.Add(mIid.Value); } //取得icode列表 Regex rIcode = new Regex(@"(?<=icode(:| = )(""|'))[\w\-]+", RegexOptions.Singleline); MatchCollection mIcodes = rIcode.Matches(tudousource); List<string> icodes = new List<string>(); foreach (Match mIcode in mIcodes) { icodes.Add(mIcode.Value); } //取得标题列表 Regex rKw = new Regex(@"(?<=kw(:| = )(""|')).+?(?=(""|'))", RegexOptions.Singleline); MatchCollection mKws = rKw.Matches(tudousource); List<string> kws = new List<string>(); foreach (Match mKw in mKws) { kws.Add(mKw.Value); } //检查需要的iid for (int i = 0; i < icodes.Count; i++) { if (request.Id.Equals(icodes[i])) { request.Id = iids[i]; pr.SpecificResult["icode"] = icodes[i]; pr.SpecificResult["title"] = kws[i]; break; } } } pr.SpecificResult["iid"] = request.Id; string xmlurl = @"http://v2.tudou.com/v?st=1%2C2%2C3%2C4%2C99&it=" + request.Id + "&pw=" + request.Password; string xmldoc = Network.GetHtmlSource(xmlurl, Encoding.UTF8, request.Proxy); Regex rVideo = new Regex("<f [^>]+brt=\"(?<brt>\\d+)\">(?<url>[^<]+)</f>"); MatchCollection mcVideo = rVideo.Matches(xmldoc); //默认url string defaultUrl = ""; //将 数字-清晰度 存入到字典中 var resolutiondict = new Dictionary<string, string>(); resolutiondict.Add("1", "流畅 256P"); resolutiondict.Add("2", "清晰 360P"); resolutiondict.Add("3", "高清 720P"); resolutiondict.Add("99", "原画"); //将 清晰度-地址 存入到字典中 var videodict = new Dictionary<string, string>(); foreach (Match item in mcVideo) { string brt = item.Groups["brt"].Value; string url = item.Groups["url"].Value; if (string.IsNullOrEmpty(defaultUrl)) defaultUrl = url; if (resolutiondict.ContainsKey(brt)) { brt = resolutiondict[brt]; } if (!videodict.ContainsValue(brt)) //不覆盖已有的 清晰度-地址 对 videodict.Add(url, brt); } //自动应答 if (request.AutoAnswers.Count > 0) { string answer; foreach (var item in request.AutoAnswers) { if (item.Prefix == "tudou") { if (resolutiondict.ContainsKey(item.Identify)) //如果自动应答设置中有"1"/"2"/"3"/"99" { answer = resolutiondict[item.Identify]; //取得描述(如"流畅 256P") foreach (var u in videodict.Keys) //从字典中查找描述信息所属的URL { if (videodict[u].Equals(answer)) { pr.Items.Add(new ParseResultItem(u)); return pr; } } } } } } string urladdress; //只在视频清晰度数量多余1个时进行选择 if (videodict.Count > 1) { urladdress = ToolForm.CreateSingleSelectForm("请选择视频清晰度:", videodict, defaultUrl, request.AutoAnswers, "tudou"); } else //如果只有一个清晰度,不进行选择 { urladdress = defaultUrl; } pr.Items.Add(new ParseResultItem(urladdress)); return pr; }
/// <summary> /// 解析土豆视频 /// </summary> /// <remarks>接受的AutoAnswer对象需要以<i>tudou</i>作为前缀</remarks> public ParseResult Parse(ParseRequest request) { ParseResult pr = new ParseResult(); int t; if (!int.TryParse(request.Id, out t)) //测试iid是否是真实的(应该为数字) { //取得土豆网页面源代码 string tudousource = Network.GetHtmlSource("http://www.tudou.com/programs/view/" + request.Id + "/", Encoding.GetEncoding("GB2312"), request.Proxy); //取得iid列表 Regex rIid = new Regex(@"(?<=iid(:| = ))\d+", RegexOptions.Singleline); MatchCollection mIids = rIid.Matches(tudousource); List <string> iids = new List <string>(); foreach (Match mIid in mIids) { iids.Add(mIid.Value); } //取得icode列表 Regex rIcode = new Regex(@"(?<=icode(:| = )(""|'))[\w\-]+", RegexOptions.Singleline); MatchCollection mIcodes = rIcode.Matches(tudousource); List <string> icodes = new List <string>(); foreach (Match mIcode in mIcodes) { icodes.Add(mIcode.Value); } //取得标题列表 Regex rKw = new Regex(@"(?<=kw(:| = )(""|')).+?(?=(""|'))", RegexOptions.Singleline); MatchCollection mKws = rKw.Matches(tudousource); List <string> kws = new List <string>(); foreach (Match mKw in mKws) { kws.Add(mKw.Value); } //检查需要的iid for (int i = 0; i < icodes.Count; i++) { if (request.Id.Equals(icodes[i])) { request.Id = iids[i]; pr.SpecificResult["icode"] = icodes[i]; pr.SpecificResult["title"] = kws[i]; break; } } } pr.SpecificResult["iid"] = request.Id; string xmlurl = @"http://v2.tudou.com/v?st=1%2C2%2C3%2C4%2C99&it=" + request.Id + "&pw=" + request.Password; string xmldoc = Network.GetHtmlSource(xmlurl, Encoding.UTF8, request.Proxy); Regex rVideo = new Regex("<f [^>]+brt=\"(?<brt>\\d+)\">(?<url>[^<]+)</f>"); MatchCollection mcVideo = rVideo.Matches(xmldoc); //默认url string defaultUrl = ""; //将 数字-清晰度 存入到字典中 var resolutiondict = new Dictionary <string, string>(); resolutiondict.Add("1", "流畅 256P"); resolutiondict.Add("2", "清晰 360P"); resolutiondict.Add("3", "高清 720P"); resolutiondict.Add("99", "原画"); //将 清晰度-地址 存入到字典中 var videodict = new Dictionary <string, string>(); foreach (Match item in mcVideo) { string brt = item.Groups["brt"].Value; string url = item.Groups["url"].Value; if (string.IsNullOrEmpty(defaultUrl)) { defaultUrl = url; } if (resolutiondict.ContainsKey(brt)) { brt = resolutiondict[brt]; } if (!videodict.ContainsValue(brt)) //不覆盖已有的 清晰度-地址 对 { videodict.Add(url, brt); } } //自动应答 if (request.AutoAnswers.Count > 0) { string answer; foreach (var item in request.AutoAnswers) { if (item.Prefix == "tudou") { if (resolutiondict.ContainsKey(item.Identify)) //如果自动应答设置中有"1"/"2"/"3"/"99" { answer = resolutiondict[item.Identify]; //取得描述(如"流畅 256P") foreach (var u in videodict.Keys) //从字典中查找描述信息所属的URL { if (videodict[u].Equals(answer)) { pr.Items.Add(new ParseResultItem(u)); return(pr); } } } } } } string urladdress; //只在视频清晰度数量多余1个时进行选择 if (videodict.Count > 1) { urladdress = ToolForm.CreateSingleSelectForm("请选择视频清晰度:", videodict, defaultUrl, request.AutoAnswers, "tudou"); } else //如果只有一个清晰度,不进行选择 { urladdress = defaultUrl; } pr.Items.Add(new ParseResultItem(urladdress)); return(pr); }
/// <summary> /// 解析优酷视频源文件地址 /// </summary> ///<remarks>自动应答会检查前缀为<i>youku</i>的所有设置</remarks> public ParseResult Parse(ParseRequest request) { ParseResult pr = new ParseResult(); string urlpre = @"http://v.youku.com/player/getPlayList/VideoIDS/%ID%/timezone/+08/version/5/source/video?n=3&ran=4656&password=%PW%"; string url = urlpre.Replace(@"%ID%", request.Id).Replace(@"%PW%", request.Password); string xmldoc = Network.GetHtmlSource(url, Encoding.UTF8, request.Proxy); //选择语言 Regex rLang = new Regex(@"(?<=""audiolang"":\[).+?(?=\])"); Match mLang = rLang.Match(xmldoc); if (mLang.Success) //如果存在多种语言 { string langs = mLang.Value; Regex rLanguage = new Regex(@"""lang"":""(?<lang>.+?)"",""vid"":""(?<vid>.+?)"""); MatchCollection mcLanguages = rLanguage.Matches(langs); /*Dictionary<string, string> langDict = new Dictionary<string, string>(); foreach (Match mLanguage in mcLanguages) { langDict.Add(mLanguage.Groups["vid"].Value, Tools.ReplaceUnicode2Str(mLanguage.Groups["lang"].Value)); } string chosenId = ToolForm.CreateSingleSelectForm("您正在下载的视频有多种语言版本,请选择语言:", langDict, "", request.AutoAnswers, "youku"); request.Id = chosenId; */ //不跳选语言框,直接选第一个 2012.09.01 request.Id = mcLanguages[0].Groups["vid"].Value; url = urlpre.Replace(@"%ID%", request.Id).Replace(@"%PW%", request.Password); xmldoc = Network.GetHtmlSource(url, Encoding.UTF8, request.Proxy); } //正则表达式提取各个参数 string regexstring = "\"seed\":(?<seed>\\w+),.+\"key1\":\"(?<key1>\\w+)\",\"key2\":\"(?<key2>\\w+)\".+\"streamfileids\":{\"(?<fileposfix>\\w+)\":\"(?<fileID>[0-9\\*]+)"; Regex r = new Regex(regexstring); Match m = r.Match(xmldoc); //提取参数 double seed = Double.Parse(m.Groups["seed"].Value); string key1 = m.Groups["key1"].Value; string key2 = m.Groups["key2"].Value; //提取各视频参数 Regex rStreamFileIds = new Regex(@"""streamfileids"":{(?<fileids>.+?)}"); Match mStreamFileIds = rStreamFileIds.Match(xmldoc); string fileIds = mStreamFileIds.Groups["fileids"].Value; var dict = new Dictionary<string, string>(); string defaultres = ""; //是否有超清模式 if (fileIds.Contains("hd2")) { dict.Add("hd2", "超清(hd2)"); defaultres = "hd2"; } //是否有高清模式 if (fileIds.Contains("mp4")) { dict.Add("mp4", "高清(mp4)"); defaultres = "mp4"; } //是否有普通清晰度 if (fileIds.Contains("flv")) { dict.Add("flv", "标清(flv)"); defaultres = "flv"; } string fileposfix = null; string strSelect = null; //自动应答 if (request.AutoAnswers.Count > 0) { foreach (var item in request.AutoAnswers) { if (item.Prefix == "youku") { if (fileIds.Contains(item.Identify)) { strSelect = item.Identify; fileposfix = item.Identify; break; } } } } if (string.IsNullOrEmpty(fileposfix)) { //如果多余一种清晰度 if (dict.Count > 1) { //fileposfix = ToolForm.CreateSingleSelectForm("您正在下载优酷视频,请选择视频清晰度:", dict, defaultres, request.AutoAnswers, "youku"); //无论如何不弹清晰度 fileposfix = defaultres; } else { fileposfix = defaultres; } strSelect = fileposfix; } //修正高清 if (fileposfix == "hd2") fileposfix = "flv"; //取得FileID Regex rFileID = new Regex(@"""" + strSelect + @""":""(?<fileid>.+?)"""); Match mFileID = rFileID.Match(fileIds); string fileID = mFileID.Groups["fileid"].Value; //2012.09.02 为了这个url而做的修改: http://v.youku.com/v_show/id_XNDQ1NTEyNTc2.html /* //提取视频个数 int flv_no = 0; string regexFlvNo = @"""segs"":{""\w+"":\[(?<content>.+?)\]"; Regex rn = new Regex(regexFlvNo); Match mn = rn.Match(xmldoc); char[] tmp_content = mn.Groups["content"].Value.ToCharArray(); foreach (char item in tmp_content) { if (item == '{') flv_no++; } */ //提取key Regex rSegs = new Regex(@"segs"":{(?<segs>.+?)},""streamsizes"); Match mSegs = rSegs.Match(xmldoc); string segs = mSegs.Groups["segs"].Value; Regex rSegsSub = new Regex(@"""" + strSelect + @""":\[(?<segssub>.+?)\]"); Match mSegsSub = rSegsSub.Match(segs); string segssub = mSegsSub.Groups["segssub"].Value; string regexKey = @"""k"":""(?<k>\w+)"",""k2"":""(?<k2>\w+)"""; MatchCollection mcKey = Regex.Matches(segssub, regexKey); List<string> keys = new List<string>(); foreach (Match mKey in mcKey) { keys.Add("?K=" + mKey.Groups["k"].Value + ",k2:" + mKey.Groups["k2"].Value); } //生成sid string sid = genSid(); //生成fileid string fileid = getFileID(fileID, seed); //生成key //string key = genKey(key1, key2); //添加各个地址 List<string> lst = new List<string>(); //12.09.02修改 http://v.youku.com/v_show/id_XNDQ1NTEyNTc2.html //for (int i = 0; i < flv_no; i++) for (int i = 0; i < keys.Count; ++i) { //得到地址 string u = "http://f.youku.com/player/getFlvPath/sid/" + sid + "_" + string.Format("{0:D2}", i) + "/st/" + fileposfix + "/fileid/" + fileid.Substring(0, 8) + string.Format("{0:D2}", i) + fileid.Substring(10) + keys[i]; //添加地址 pr.Items.Add(new ParseResultItem(u)); } //提取各项详细信息 MatchCollection mcSegs = Regex.Matches(segssub, @"{.+?}"); for (int i = 0; i < mcSegs.Count; i++) { MatchCollection mcKeys = Regex.Matches(mcSegs[i].Value, @"""(?<key>\w+)"":""(?<value>\w+)"""); foreach (Match mkey in mcKeys) { string k = mkey.Groups["key"].Value; string v = mkey.Groups["value"].Value; //修正length和order if (k.Equals("seconds")) { k = "length"; v = (Int32.Parse(v) * 1000).ToString(); } if (k.Equals("no")) k = "order"; pr.Items[i].Information.Add(k, v); } } return pr; }
/// <summary> /// 解析土豆视频 /// </summary> /// <remarks>接受的AutoAnswer对象需要以<i>tudou</i>作为前缀</remarks> public ParseResult Parse(ParseRequest request) { ParseResult pr = new ParseResult(); int t; if (!int.TryParse(request.Id, out t)) //测试iid是否是真实的(应该为数字) { //取得土豆网页面源代码 string tudousource = Network.GetHtmlSource("http://www.tudou.com/programs/view/" + request.Id + "/", Encoding.GetEncoding("GB2312"), request.Proxy); //取得iid列表 Regex rIid = new Regex(@"(?<=iid(:| = ))\d+", RegexOptions.Singleline); MatchCollection mIids = rIid.Matches(tudousource); List<string> iids = new List<string>(); foreach (Match mIid in mIids) { iids.Add(mIid.Value); } //取得icode列表 Regex rIcode = new Regex(@"(?<=icode(:| = )(""|'))[\w\-]+", RegexOptions.Singleline); MatchCollection mIcodes = rIcode.Matches(tudousource); List<string> icodes = new List<string>(); foreach (Match mIcode in mIcodes) { icodes.Add(mIcode.Value); } //取得标题列表 Regex rKw = new Regex(@"(?<=kw(:| = )(""|')).+?(?=(""|'))", RegexOptions.Singleline); MatchCollection mKws = rKw.Matches(tudousource); List<string> kws = new List<string>(); foreach (Match mKw in mKws) { kws.Add(mKw.Value); } //检查需要的iid for (int i = 0; i < icodes.Count; i++) { if (request.Id.Equals(icodes[i])) { request.Id = iids[i]; pr.SpecificResult["icode"] = icodes[i]; pr.SpecificResult["title"] = kws[i]; break; } } } pr.SpecificResult["iid"] = request.Id; //string xmlurl = @"http://v2.tudou.com/v?st=1%2C2%2C3%2C4%2C99&it=" + request.Id + "&pw=" + request.Password; string xmlurl = @"http://v2.tudou.com/f?sender=pepper&v=4.2.2&sj=1&id=" + request.Id + "&sid=10000&r=6226"; string xmldoc = Network.GetHtmlSource(xmlurl, Encoding.UTF8, request.Proxy); xmldoc = xmldoc.Replace("<a>", "").Replace("</a>", "").Replace("<b>", "").Replace("</b>", ""); if (xmldoc.StartsWith("<f")) { xmldoc = "<v>" + xmldoc + "</v>"; } //反序列化XML文档 TudouVideo tudou; var serializer = new XmlSerializer(typeof(TudouVideo)); using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(xmldoc))) { tudou = (TudouVideo)serializer.Deserialize(ms); } //Regex rVideo = new Regex("<f [^>]+brt=\"(?<brt>\\d+)\">(?<url>[^<]+)</f>"); //MatchCollection mcVideo = rVideo.Matches(xmldoc); //默认url string defaultUrl = ""; //将 数字-清晰度 存入到字典中 var resolutiondict = new Dictionary<string, string>(); resolutiondict.Add("1", "流畅"); resolutiondict.Add("2", "清晰"); resolutiondict.Add("3", "高清"); resolutiondict.Add("4", "超清"); resolutiondict.Add("99", "原画"); //将 清晰度-地址 存入到字典中 var videodict = new Dictionary<string, string>(); //foreach (Match item in mcVideo) foreach (var info in tudou.videos) { string brt = info.brt ?? "1"; // item.Groups["brt"].Value; string url = info.address; // item.Groups["url"].Value; if (string.IsNullOrEmpty(defaultUrl)) defaultUrl = url; brt = resolutiondict[brt]; if (!videodict.ContainsValue(brt)) //不覆盖已有的 清晰度-地址 对 videodict.Add(url, brt); } //自动应答 if (request.AutoAnswers != null && request.AutoAnswers.Count > 0) { string answer; foreach (var item in request.AutoAnswers) { if (item.Prefix == "tudou") { if (resolutiondict.ContainsKey(item.Identify)) //如果自动应答设置中有"1"/"2"/"3"/"99" { answer = resolutiondict[item.Identify]; //取得描述(如"流畅 256P") foreach (var u in videodict.Keys) //从字典中查找描述信息所属的URL { if (videodict[u].Equals(answer)) { pr.Items.Add(new ParseResultItem(u)); return pr; } } } } } } string urladdress; //只在视频清晰度数量多余1个时进行选择 if (videodict.Count > 1) { urladdress = ToolForm.CreateSingleSelectForm("请选择视频清晰度:", videodict, defaultUrl, request.AutoAnswers, "tudou"); } else //如果只有一个清晰度,不进行选择 { urladdress = defaultUrl; } pr.Items.Add(new ParseResultItem(urladdress)); pr.Items[0].Information.Add("order", "1"); //写入视频时长 pr.Items[0].Information.Add("length", tudou.time); pr.SpecificResult.Add("totallength", tudou.time); return pr; }
/// <summary> /// 解析土豆视频 /// </summary> /// <remarks>接受的AutoAnswer对象需要以<i>tudou</i>作为前缀</remarks> public ParseResult Parse(ParseRequest request) { ParseResult pr = new ParseResult(); int t; if (!int.TryParse(request.Id, out t)) //测试iid是否是真实的(应该为数字) { //取得土豆网页面源代码 string tudousource = Network.GetHtmlSource("http://www.tudou.com/programs/view/" + request.Id + "/", Encoding.GetEncoding("GB2312"), request.Proxy); //取得iid列表 Regex rIid = new Regex(@"(?<=iid(:| = ))\d+", RegexOptions.Singleline); MatchCollection mIids = rIid.Matches(tudousource); List <string> iids = new List <string>(); foreach (Match mIid in mIids) { iids.Add(mIid.Value); } //取得icode列表 Regex rIcode = new Regex(@"(?<=icode(:| = )(""|'))[\w\-]+", RegexOptions.Singleline); MatchCollection mIcodes = rIcode.Matches(tudousource); List <string> icodes = new List <string>(); foreach (Match mIcode in mIcodes) { icodes.Add(mIcode.Value); } //取得标题列表 Regex rKw = new Regex(@"(?<=kw(:| = )(""|')).+?(?=(""|'))", RegexOptions.Singleline); MatchCollection mKws = rKw.Matches(tudousource); List <string> kws = new List <string>(); foreach (Match mKw in mKws) { kws.Add(mKw.Value); } //检查需要的iid for (int i = 0; i < icodes.Count; i++) { if (request.Id.Equals(icodes[i])) { request.Id = iids[i]; pr.SpecificResult["icode"] = icodes[i]; pr.SpecificResult["title"] = kws[i]; break; } } } pr.SpecificResult["iid"] = request.Id; //string xmlurl = @"http://v2.tudou.com/v?st=1%2C2%2C3%2C4%2C99&it=" + request.Id + "&pw=" + request.Password; string xmlurl = @"http://v2.tudou.com/f?sender=pepper&v=4.2.2&sj=1&id=" + request.Id + "&sid=10000&r=6226"; string xmldoc = Network.GetHtmlSource(xmlurl, Encoding.UTF8, request.Proxy); xmldoc = xmldoc.Replace("<a>", "").Replace("</a>", "").Replace("<b>", "").Replace("</b>", ""); if (xmldoc.StartsWith("<f")) { xmldoc = "<v>" + xmldoc + "</v>"; } //反序列化XML文档 TudouVideo tudou; var serializer = new XmlSerializer(typeof(TudouVideo)); using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(xmldoc))) { tudou = (TudouVideo)serializer.Deserialize(ms); } //Regex rVideo = new Regex("<f [^>]+brt=\"(?<brt>\\d+)\">(?<url>[^<]+)</f>"); //MatchCollection mcVideo = rVideo.Matches(xmldoc); //默认url string defaultUrl = ""; //将 数字-清晰度 存入到字典中 var resolutiondict = new Dictionary <string, string>(); resolutiondict.Add("1", "流畅"); resolutiondict.Add("2", "清晰"); resolutiondict.Add("3", "高清"); resolutiondict.Add("4", "超清"); resolutiondict.Add("99", "原画"); //将 清晰度-地址 存入到字典中 var videodict = new Dictionary <string, string>(); //foreach (Match item in mcVideo) foreach (var info in tudou.videos) { string brt = info.brt ?? "1"; // item.Groups["brt"].Value; string url = info.address; // item.Groups["url"].Value; if (string.IsNullOrEmpty(defaultUrl)) { defaultUrl = url; } brt = resolutiondict[brt]; if (!videodict.ContainsValue(brt)) //不覆盖已有的 清晰度-地址 对 { videodict.Add(url, brt); } } //自动应答 if (request.AutoAnswers != null && request.AutoAnswers.Count > 0) { string answer; foreach (var item in request.AutoAnswers) { if (item.Prefix == "tudou") { if (resolutiondict.ContainsKey(item.Identify)) //如果自动应答设置中有"1"/"2"/"3"/"99" { answer = resolutiondict[item.Identify]; //取得描述(如"流畅 256P") foreach (var u in videodict.Keys) //从字典中查找描述信息所属的URL { if (videodict[u].Equals(answer)) { pr.Items.Add(new ParseResultItem(u)); return(pr); } } } } } } string urladdress; //只在视频清晰度数量多余1个时进行选择 if (videodict.Count > 1) { urladdress = ToolForm.CreateSingleSelectForm("请选择视频清晰度:", videodict, defaultUrl, request.AutoAnswers, "tudou"); } else //如果只有一个清晰度,不进行选择 { urladdress = defaultUrl; } pr.Items.Add(new ParseResultItem(urladdress)); pr.Items[0].Information.Add("order", "1"); //写入视频时长 pr.Items[0].Information.Add("length", tudou.time); pr.SpecificResult.Add("totallength", tudou.time); return(pr); }
/// <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; }