2014-01-24 93 views
2

有很多類似性質的問題,但至今我無法找到任何直接回答此問題的內容。很多回復包括「查看這個源代碼」幷包含一個鏈接,不幸的是我很難分析這些鏈接中的源代碼,所以我希望有人能夠一步一步地給我一些東西。從YouTube獲取FLV URL

這是我到目前爲止有:從最終用戶(例如www.youtube.com/watch?v=2FlgVN03fNM)

  • 發送HTTP請求的URL

    1. 請求鏈接,獲取源。
    2. 正則表達式源頭上找了一些資料(大概一系列可連接起來形成一個鏈接到FLV元素。
    3. 下載的FLV。
    4. 轉換的FLV轉換成MP3或您想取格式。

    我已經實現步驟1,2,5,和他們都做正是我想要的,但似乎還有圍繞着如何執行步驟3.可能有人打破這種不明確再向下一點?例如:

    1. 正則表達式「XXXXXXXXX」
    2. 這一行,你需要
    3. 分割字符串由「YYY」獲取的元素列表
    4. 找到所有匹配「ZZZZZ」
    5. 使用該元素的所有信息那些創建FLV鏈接的元素

    這對我非常有用,如果可能的話,我會喜歡在C#或PHP中提取鏈接的步驟或非常簡單的應用程序。

  • +0

    你需要一個HTML解析器。 http://htmlagilitypack.codeplex.com – SLaks

    +0

    這真的不能用RegEx實現嗎?或者更好的是,在.NET中使用字符串操作? – XtrmJosh

    +0

    你可以顯式*一些信息*? – Stephan

    回答

    2

    如果你想跳過這個簡單的代碼示例,可以看到在GitHub完整的源代碼:https://github.com/XtrmJosh/YouTubeDownloader

    我是非常正確的與我的假設,雖然它是我花10個小時左右,我終於實現了我的目標。這是一個粗略的故障:

    1. 逃生繩,以確保我們不會破壞任何東西
    2. 運行一些花哨的正則表達式,什麼不能捕捉到的字符串的確切領域,我們正在尋找
    3. 查找簽名和我們發現每個網址中都沒有(我們會發現很多,我們需要在它們可以使用之前將它們縮小一點點)
    4. 添加我們爲每個網址找到的簽名,否則我們會得到垃圾文件
    5. 掃描一些itags,所以我們知道哪個文件類型與每個鏈接相關聯 - 我只有想要FLV文件。
    6. 將視頻名稱追加到URL中,然後下載。

    因此,這裏是我使用的是得到一個HTML文檔中的所有視頻的網址(僅限YouTube - 至今)代碼

    public static List<string> ExtractUrls(string html) 
        { 
         string title = GetTitle(html); 
    
         List<string> urls = new List<string>(); 
         string DataBlockStart = "\"url_encoded_fmt_stream_map\":\\s+\"(.+?)&"; // Marks start of Javascript Data Block 
    
         html = Uri.UnescapeDataString(Regex.Match(html, DataBlockStart, RegexOptions.Singleline).Groups[1].ToString()); 
    
         string firstPatren = html.Substring(0, html.IndexOf('=') + 1); 
         var matchs = Regex.Split(html, firstPatren); 
         for (int i = 0; i < matchs.Length; i++) 
          matchs[i] = firstPatren + matchs[i]; 
         foreach (var match in matchs) 
         { 
          if (!match.Contains("url=")) continue; 
    
          string url = GetTxtBtwn(match, "url=", "\\u0026", 0, false); 
          if (url == "") url = GetTxtBtwn(match, "url=", ",url", 0, false); 
          if (url == "") url = GetTxtBtwn(match, "url=", "\",", 0, false); 
    
          string sig = GetTxtBtwn(match, "sig=", "\\u0026", 0, false); 
          if (sig == "") sig = GetTxtBtwn(match, "sig=", ",sig", 0, false); 
          if (sig == "") sig = GetTxtBtwn(match, "sig=", "\",", 0, false); 
    
          while ((url.EndsWith(",")) || (url.EndsWith(".")) || (url.EndsWith("\""))) 
           url = url.Remove(url.Length - 1, 1); 
    
          while ((sig.EndsWith(",")) || (sig.EndsWith(".")) || (sig.EndsWith("\""))) 
           sig = sig.Remove(sig.Length - 1, 1); 
    
          if (string.IsNullOrEmpty(url)) continue; 
          if (!string.IsNullOrEmpty(sig)) 
           url += "&signature=" + sig; 
          urls.Add(url); 
         } 
    
         for (int i = 0; i < urls.Count; i++) 
         { 
          urls[i] += "&title="; 
          urls[i] += title; 
         } 
    
         return urls; 
        } 
    
        public static string GetTitle(string RssDoc) 
        { 
         string str14 = GetTxtBtwn(RssDoc, "'VIDEO_TITLE': '", "'", 0, false); 
         if (str14 == "") str14 = GetTxtBtwn(RssDoc, "\"title\" content=\"", "\"", 0, false); 
         if (str14 == "") str14 = GetTxtBtwn(RssDoc, "&title=", "&", 0, false); 
         str14 = str14.Replace(@"\", "").Replace("'", "&#39;").Replace("\"", "&quot;").Replace("<", "&lt;").Replace(">", "&gt;").Replace("+", " "); 
         return str14; 
        } 
    
        public static string GetTxtBtwn(string input, string start, string end, int startIndex, bool UseLastIndexOf) 
        { 
         int index1 = UseLastIndexOf ? input.LastIndexOf(start, startIndex) : 
                 input.IndexOf(start, startIndex); 
         if (index1 == -1) return ""; 
         index1 += start.Length; 
         int index2 = input.IndexOf(end, index1); 
         if (index2 == -1) return input.Substring(index1); 
         return input.Substring(index1, index2 - index1); 
        } 
    

    此代碼將(與當前的YouTube格式)提供一個FLV文件的鏈接,你可以下載並做你喜歡的(在YouTube的TOS內)。然後我用這從那些本規範規定找到最優質的鏈接:

    public static string GetFLV(List<string> urls) 
        { 
         // Acquire a list of links which match the criteria for being FLV files 
         List<string> flvurls = new List<string>(); 
         foreach (string url in urls) 
         { 
          string itag = Regex.Match(url, @"itag=([1-9]?[0-9]?[0-9])", RegexOptions.Singleline).Groups[1].ToString(); 
          int itagint; 
          int.TryParse(itag, out itagint); 
    
          if (itagint == 5 || itagint == 6 || itagint == 34 || itagint == 35) 
          { 
           flvurls.Add(url); 
          } 
         } 
    
         // If we didn't find any FLVs, we return a fatal error and cause a bug later on 
         if (flvurls.Count == 0) 
         { 
          MessageBox.Show("Fatal error | iTag could not be found for FLV filetype. Please contact software vendor for assistance."); 
          return ""; 
         } 
         // If we did find some FLVs, we need to find the highest quality FLV 
         else 
         { 
          #region findBestFLV 
          foreach (string url in flvurls) 
          { 
           string itag = Regex.Match(url, @"itag=([1-9]?[0-9]?[0-9])", RegexOptions.Singleline).Groups[1].ToString(); 
           int itagint; 
           int.TryParse(itag, out itagint); 
           if (itagint == 35) 
           { 
            return url; 
           } 
          } 
          foreach (string url in flvurls) 
          { 
           string itag = Regex.Match(url, @"itag=([1-9]?[0-9]?[0-9])", RegexOptions.Singleline).Groups[1].ToString(); 
           int itagint; 
           int.TryParse(itag, out itagint); 
           if (itagint == 34) 
           { 
            return url; 
           } 
          } 
          foreach (string url in flvurls) 
          { 
           string itag = Regex.Match(url, @"itag=([1-9]?[0-9]?[0-9])", RegexOptions.Singleline).Groups[1].ToString(); 
           int itagint; 
           int.TryParse(itag, out itagint); 
           if (itagint == 6) 
           { 
            return url; 
           } 
          } 
          foreach (string url in flvurls) 
          { 
           string itag = Regex.Match(url, @"itag=([1-9]?[0-9]?[0-9])", RegexOptions.Singleline).Groups[1].ToString(); 
           int itagint; 
           int.TryParse(itag, out itagint); 
           if (itagint == 5) 
           { 
            return url; 
           } 
          } 
          #endregion 
         } 
         MessageBox.Show("Fatal error | Something has gone horrible wrong whilst finding the best FLV to use. Run, brave warrior, for the end is near."); 
         return ""; 
        } 
    

    注意它是在一分鐘很零碎,代碼的其餘部分大多是片斷我一直借錢略加編輯,但這一點我從頭腦裏寫了一些匆忙的嘗試,爲SOF找到一些東西。

    希望這有助於別人:)

    4

    這是基於Pafy更簡潔的方式:

    using System; 
    using System.Linq; 
    using HttpUtility = System.Web.HttpUtility; 
    using NameValueCollection = System.Collections.Specialized.NameValueCollection; 
    using WebClient = System.Net.WebClient; 
    
    class Program { 
        public static void Main(string[] args) { 
         string videoID = "2FlgVN03fNM"; 
         string[] itagByPriority = {"5", "6", "34", "35"}; 
    
         string videoUrl = "https://www.youtube.com/get_video_info?asv=3&el=detailpage&hl=en_US&video_id=" + videoID; 
         string encodedVideo = null; 
    
         using (var client = new WebClient()) { 
          encodedVideo = client.DownloadString(videoUrl); 
         } 
    
         NameValueCollection video = HttpUtility.ParseQueryString(encodedVideo); 
    
         string encodedStreamsCommaDelimited = video["url_encoded_fmt_stream_map"]; 
         string[] encodedStreams = encodedStreamsCommaDelimited.Split(new char[]{','}); 
         var streams = encodedStreams.Select(s => HttpUtility.ParseQueryString(s)); 
    
         var streamsByPriority = streams.OrderBy(s => Array.IndexOf(itagByPriority, s["itag"])); 
         NameValueCollection preferredStream = streamsByPriority.LastOrDefault(); 
    
         if (preferredStream != null) { 
          Console.WriteLine("{0}&signature={1}", preferredStream["url"], preferredStream["sig"]); 
         } 
        } 
    } 
    
    +0

    您的答案確實比我的整潔得多,但我覺得在同一時間理解起來有點困難,由於廣泛的方法嵌套(我認爲這是term - preferredStream = ~~~有點長我喜歡,我會upvote無論如何,但會採取我自己的答案,除非別的東西出現,謝謝! – XtrmJosh

    +0

    這通常被稱爲「方法鏈「,我喜歡這種風格,但我同意由於缺乏變量名,這很難理解,我已經將其轉換爲更易於理解的傳統風格。 – jonahb