2014-01-24 5 views
2

Есть много вопросов очень похожего характера, но пока я не могу найти ничего, что напрямую отвечает на этот вопрос. Многие ответы включают «посмотрите на исходный код этого» и содержат ссылку, к сожалению, я изо всех сил пытаюсь проанализировать исходный код в этих ссылках, поэтому я надеюсь, что кто-то может дать мне что-то шаг за шагом.Получите URL-адрес FLV с YouTube

Вот то, что я до сих пор:

  1. Запрос ссылку с конечным пользователем (например www.youtube.com/watch?v=2FlgVN03fNM)
  2. Отправить HTTP запрос к URL, приобрести источник.
  3. Regex источник, чтобы найти какую-то информацию (предположительно ряд элементов, которые могут быть объединены, чтобы сформировать ссылку на FLV.
  4. Скачать FLV.
  5. Преобразование FLV в MP3 или любой другой формат, который вы хотели бы .

Я уже достиг стадии 1, 2, 5, и все они делают именно то, что я хочу, но мне кажется, есть недостаток ясности вокруг того, как сделать шаг 3. Может ли кто-то пожалуйста перерыва это ниже: Пример:

  1. Regex для «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. Run некоторых фантазий RegEx и то, что не захватить точную области строки мы ищем
  3. Найти подписи и что не в каждом из URL-адресов, которые мы находим (мы найдем много, и нам нужно сузить их до конца до их использования)
  4. Добавьте подпись, которую мы найдем для каждого URL-адреса, в противном случае мы получим файлы мусора
  5. Сканирование некоторых itags, поэтому мы знаем, какой тип файла связан с каждой ссылкой - I только хочу файлы 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-файл, который вы можете загружать и делать, что вам нравится (в TOS YouTube). Затем я использовал это, чтобы найти самое высокое качество связи с тем, что этот код при условии:

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

Ваш ответ действительно значительно более аккуратный, чем мой, но я чувствую, что несколько сложнее понять в то же время , из-за обширного метода вложенности (я думаю, что это термин - preferredStream = ~~~ немного длинный для моей симпатии.Я буду повышать независимо, но возьму свой собственный ответ, если что-то еще не появится. Спасибо! – XtrmJosh

+0

Это обычно называется " «Мне нравится этот стиль, но я согласен с тем, что его трудно понять из-за отсутствия имен переменных. Я превратил его в более традиционный стиль, который может быть проще понять. – jonahb

Смежные вопросы