【问题标题】:Extract the video ID from youtube url in .net从 .net 中的 youtube url 中提取视频 ID
【发布时间】:2017-02-08 05:07:49
【问题描述】:

我正在努力使用正则表达式从 youtube 网址中提取视频 ID。

"(?:.+?)?(?:\\/v\\/|watch\\/|\\?v=|\\&v=|youtu\\.be\\/|\\/v=|^youtu\\.be\\/)([a-zA-Z0-9_-]{11})+";

它可以工作,因为它与视频 ID 匹配,但我想在 youtube 域中限制它,如果域与 youtube.com 或 youtu.be 不同,我不希望它与 id 匹配。不幸的是,我无法理解这个正则表达式来应用限制。

我只想在域为时匹配 id:

  • www.youtube.com
  • youtube.com
  • youtu.be
  • www.youtu.be

前面有http或https(或没有)

上述正则表达式成功匹配以下示例的 youtube id:

"http://youtu.be/AAAAAAAAA01"
"http://www.youtube.com/embed/watch?feature=player_embedded&v=AAAAAAAAA02"
"http://www.youtube.com/embed/watch?v=AAAAAAAAA03"
"http://www.youtube.com/embed/v=AAAAAAAAA04"
"http://www.youtube.com/watch?feature=player_embedded&v=AAAAAAAAA05"
"http://www.youtube.com/watch?v=AAAAAAAAA06"
"http://www.youtube.com/v/AAAAAAAAA07"
"www.youtu.be/AAAAAAAAA08"
"youtu.be/AAAAAAAAA09"
"http://www.youtube.com/watch?v=i-AAAAAAA14&feature=related"
"http://www.youtube.com/attribution_link?u=/watch?v=AAAAAAAAA15&feature=share&a=9QlmP1yvjcllp0h3l0NwuA"
"http://www.youtube.com/attribution_link?a=fF1CWYwxCQ4&u=/watch?v=AAAAAAAAA16&feature=em-uploademail"
"http://www.youtube.com/attribution_link?a=fF1CWYwxCQ4&feature=em-uploademail&u=/watch?v=AAAAAAAAA17"
"http://www.youtube.com/v/A-AAAAAAA18?fs=1&rel=0"
"http://www.youtube.com/watch/AAAAAAAAA11"

现在检查 url 的当前代码是:

private const string YoutubeLinkRegex = "(?:.+?)?(?:\\/v\\/|watch\\/|\\?v=|\\&v=|youtu\\.be\\/|\\/v=|^youtu\\.be\\/)([a-zA-Z0-9_-]{11})+";
    private static Regex regexExtractId = new Regex(YoutubeLinkRegex, RegexOptions.Compiled);


    public string ExtractVideoIdFromUrl(string url)
    {
        //extract the id
        var regRes = regexExtractId.Match(url);
        if (regRes.Success)
        {
            return regRes.Groups[1].Value;
        }
        return null;
    }

【问题讨论】:

标签: c# .net regex


【解决方案1】:

正如septihhere所说的

我玩弄了这些示例并想出了这些: .

Youtube:youtu(?:\.be|be\.com)/(?:.*v(?:/|=)|(?:.*/)?)([a-zA-Z0-9-_]+) 他们应该匹配所有给定的。 (?: ...) 表示括号内的所有内容都不会被捕获。所以应该只获取id。

【讨论】:

  • 我建议使用 {11} 而不是末尾的 +,因为大多数(如果不是全部)视频 ID 的长度为 11 个字符。 youtu(?:\.be|be\.com)/(?:.*v(?:/|=)|(?:.*/)?)([a-zA-Z0-9-_]{ 11})
【解决方案2】:

这里不需要使用正则表达式

var url = @"https://www.youtube.com/watch?v=6QlW4m9xVZY";
var uri = new Uri(url);

// you can check host here => uri.Host <= "www.youtube.com"

var query = HttpUtility.ParseQueryString(uri.Query);
var videoId = query["v"];

// videoId = 6QlW4m9xVZY

好的,当您将 v=videoId 作为参数时,上面的示例正在运行。如果你有 videoId 作为段,你可以使用这个:

var url = "http://youtu.be/AAAAAAAAA09";
var uri = new Uri(url);

var videoid = uri.Segments.Last(); // AAAAAAAAA09

结合在一起,我们可以得到

var url = @"https://www.youtube.com/watch?v=Lvcyj1GfpGY&list=PLolZLFndMkSIYef2O64OLgT-njaPYDXqy";
var uri = new Uri(url);

// you can check host here => uri.Host <= "www.youtube.com"

var query = HttpUtility.ParseQueryString(uri.Query);

var videoId = string.Empty;

if (query.AllKeys.Contains("v"))
{
    videoId = query["v"];
}
else
{
    videoId = uri.Segments.Last();
}

当然,我对您的要求一无所知,但是,希望对您有所帮助。

【讨论】:

  • 当存在其他更具可读性的选项时,我个人不喜欢使用 RegEx - 我比我自己更喜欢这个答案:)
  • 哦!我喜欢这个答案!旁注,如果您还没有这样做,则需要为HttpUtility 添加对 System.Web 的引用。
  • 不幸的是,它不适用于:youtu.be/AAAAAAAAA09、www.youtube.com/watch/aaaaaaaaaa、www.youtube.com/v/aaaaaaaa
  • @MenelaosVergis 这些域示例均未在原始问题中列出。如果您有更多需要,请更新原始问题。
  • 谢谢,伙计们。我更新了以 videoId 作为 Url 段的视频的答案。
【解决方案3】:

问题是正则表达式无法在挖掘操作之前检查所需的字符串,同时将此字符串用作挖掘操作本身。

例如让我们检查"http://www.youtu.be/v/AAAAAAAAA07" YouTu.be是URL开头的必填项,但挖矿动作是"/v/(11 chars)"

"http://www.youtu.be/AAAAAAAAA07",挖矿操作是"youtu.be/(11 chars)"

这不能在同一个正则表达式中,这就是为什么我们不能检查域在同一个正则表达式中提取 id。

我决定从有效域列表中检查域权限,然后从 URL 中提取 id。

 private const string YoutubeLinkRegex = "(?:.+?)?(?:\\/v\\/|watch\\/|\\?v=|\\&v=|youtu\\.be\\/|\\/v=|^youtu\\.be\\/)([a-zA-Z0-9_-]{11})+";
 private static Regex regexExtractId = new Regex(YoutubeLinkRegex, RegexOptions.Compiled);
 private static string[] validAuthorities = { "youtube.com", "www.youtube.com", "youtu.be", "www.youtu.be" };

 public string ExtractVideoIdFromUri(Uri uri)
 {
     try
     {
        string authority = new UriBuilder(uri).Uri.Authority.ToLower();

        //check if the url is a youtube url
        if (validAuthorities.Contains(authority))
        {
            //and extract the id
            var regRes = regexExtractId.Match(uri.ToString());
            if (regRes.Success)
            {
                return regRes.Groups[1].Value;
            }
        }
     }catch{}


     return null;
 }

UriBuilder 是首选,因为它可以理解比Uri 类更广泛的 URL。它可以从不包含"youtube.com"等方案的URL创建Uri

该函数返回 null(正确)并带有以下测试 URL:

"ww.youtube.com/v/AAAAAAAAA13"
"http:/www.youtube.com/v/AAAAAAAAA13"
"http://www.youtub1e.com/v/AAAAAAAAA13"
"http://www.vimeo.com/v/AAAAAAAAA13"
"www.youtube.com/b/AAAAAAAAA13"
"www.youtube.com/v/AAAAAAAAA1"
"www.youtube.com/v/AAAAAAAAA1&"
"www.youtube.com/v/AAAAAAAAA1/"
".youtube.com/v/AAAAAAAAA13"

【讨论】:

    【解决方案4】:

    url 没有诸如“www.youtu.be/AAAAAAAAA08”之类的方案时,tym32167 的答案会在var uri = new Uri(url); 处引发异常。

    此外,某些网址返回错误的videoIds。

    这是我基于 tym32167 的代码。

        static private string GetYouTubeVideoIdFromUrl(string url)
        {
            Uri uri = null;
            if (!Uri.TryCreate(url, UriKind.Absolute, out uri))
            {
                try
                {
                    uri = new UriBuilder("http", url).Uri;
                }
                catch
                {
                    // invalid url
                    return "";
                }
            }
    
            string host = uri.Host;
            string[] youTubeHosts = { "www.youtube.com", "youtube.com", "youtu.be", "www.youtu.be" };
            if (!youTubeHosts.Contains(host))
                return "";
    
            var query = HttpUtility.ParseQueryString(uri.Query);
    
            if (query.AllKeys.Contains("v"))
            {
                return Regex.Match(query["v"], @"^[a-zA-Z0-9_-]{11}$").Value;
            }
            else if (query.AllKeys.Contains("u"))
            {
                // some urls have something like "u=/watch?v=AAAAAAAAA16"
                return Regex.Match(query["u"], @"/watch\?v=([a-zA-Z0-9_-]{11})").Groups[1].Value;
            }
            else
            {
                // remove a trailing forward space
                var last = uri.Segments.Last().Replace("/", "");
                if (Regex.IsMatch(last, @"^v=[a-zA-Z0-9_-]{11}$"))
                    return last.Replace("v=", "");
    
                string[] segments = uri.Segments;
                if (segments.Length > 2 && segments[segments.Length - 2] != "v/" && segments[segments.Length - 2] != "watch/")
                    return "";
    
                return Regex.Match(last, @"^[a-zA-Z0-9_-]{11}$").Value;
            }
        }
    

    让我们测试一下。

            string[] urls = {"http://youtu.be/AAAAAAAAA01",
                "http://www.youtube.com/embed/watch?feature=player_embedded&v=AAAAAAAAA02",
                "http://www.youtube.com/embed/watch?v=AAAAAAAAA03",
                "http://www.youtube.com/embed/v=AAAAAAAAA04",
                "http://www.youtube.com/watch?feature=player_embedded&v=AAAAAAAAA05",
                "http://www.youtube.com/watch?v=AAAAAAAAA06",
                "http://www.youtube.com/v/AAAAAAAAA07",
                "www.youtu.be/AAAAAAAAA08",
                "youtu.be/AAAAAAAAA09",
                "http://www.youtube.com/watch?v=i-AAAAAAA14&feature=related",
                "http://www.youtube.com/attribution_link?u=/watch?v=AAAAAAAAA15&feature=share&a=9QlmP1yvjcllp0h3l0NwuA",
                "http://www.youtube.com/attribution_link?a=fF1CWYwxCQ4&u=/watch?v=AAAAAAAAA16&feature=em-uploademail",
                "http://www.youtube.com/attribution_link?a=fF1CWYwxCQ4&feature=em-uploademail&u=/watch?v=AAAAAAAAA17",
                "http://www.youtube.com/v/A-AAAAAAA18?fs=1&rel=0",
                "http://www.youtube.com/watch/AAAAAAAAA11",};
    
            Console.WriteLine("***Youtube urls***");
            foreach (string url in urls)
            {
                Console.WriteLine("{0}\n-> {1}", url, GetYouTubeVideoIdFromUrl(url));
            }
    
            string[] invalidUrls = {
                "ww.youtube.com/v/AAAAAAAAA13",
                "http:/www.youtube.com/v/AAAAAAAAA13",
                "http://www.youtub1e.com/v/AAAAAAAAA13",
                "http://www.vimeo.com/v/AAAAAAAAA13",
                "www.youtube.com/b/AAAAAAAAA13",
                "www.youtube.com/v/AAAAAAAAA1",
                "www.youtube.com/v/AAAAAAAAA1&",
                "www.youtube.com/v/AAAAAAAAA1/",
                ".youtube.com/v/AAAAAAAAA13"};
    
            Console.WriteLine("***Invalid youtube urls***");
            foreach (string url in invalidUrls)
            {
                Console.WriteLine("{0}\n-> {1}", url, GetYouTubeVideoIdFromUrl(url));
            }
    

    结果(一切正常)

    ***Youtube urls***
    http://youtu.be/AAAAAAAAA01
    -> AAAAAAAAA01
    http://www.youtube.com/embed/watch?feature=player_embedded&v=AAAAAAAAA02
    -> AAAAAAAAA02
    http://www.youtube.com/embed/watch?v=AAAAAAAAA03
    -> AAAAAAAAA03
    http://www.youtube.com/embed/v=AAAAAAAAA04
    -> AAAAAAAAA04
    http://www.youtube.com/watch?feature=player_embedded&v=AAAAAAAAA05
    -> AAAAAAAAA05
    http://www.youtube.com/watch?v=AAAAAAAAA06
    -> AAAAAAAAA06
    http://www.youtube.com/v/AAAAAAAAA07
    -> AAAAAAAAA07
    www.youtu.be/AAAAAAAAA08
    -> AAAAAAAAA08
    youtu.be/AAAAAAAAA09
    -> AAAAAAAAA09
    http://www.youtube.com/watch?v=i-AAAAAAA14&feature=related
    -> i-AAAAAAA14
    http://www.youtube.com/attribution_link?u=/watch?v=AAAAAAAAA15&feature=share&a=9QlmP1yvjcllp0h3l0NwuA
    -> AAAAAAAAA15
    http://www.youtube.com/attribution_link?a=fF1CWYwxCQ4&u=/watch?v=AAAAAAAAA16&feature=em-uploademail
    -> AAAAAAAAA16
    http://www.youtube.com/attribution_link?a=fF1CWYwxCQ4&feature=em-uploademail&u=/watch?v=AAAAAAAAA17
    -> AAAAAAAAA17
    http://www.youtube.com/v/A-AAAAAAA18?fs=1&rel=0
    -> A-AAAAAAA18
    http://www.youtube.com/watch/AAAAAAAAA11
    -> AAAAAAAAA11
    
    
    
    ***Invalid youtube urls***
    ww.youtube.com/v/AAAAAAAAA13
    -> 
    http:/www.youtube.com/v/AAAAAAAAA13
    -> 
    http://www.youtub1e.com/v/AAAAAAAAA13
    -> 
    http://www.vimeo.com/v/AAAAAAAAA13
    -> 
    www.youtube.com/b/AAAAAAAAA13
    -> 
    www.youtube.com/v/AAAAAAAAA1
    -> 
    www.youtube.com/v/AAAAAAAAA1&
    -> 
    www.youtube.com/v/AAAAAAAAA1/
    -> 
    .youtube.com/v/AAAAAAAAA13
    -> 
    

    【讨论】:

      【解决方案5】:

      应该这样做:

      public static string GetYouTubeId(string url) {
          var regex = @"(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?|watch)\/|.*[?&amp;]v=)|youtu\.be\/)([^""&amp;?\/ ]{11})";
      
          var match = Regex.Match(url, regex);
      
          if (match.Success)
          {
              return match.Groups[1].Value;
          }
      
          return url;
        }
      

      【讨论】:

        【解决方案6】:

        这是我在先前答案中添加了安全检查的 $.02,以确保您不会在某些极端情况输入时遇到 Length cannot be less than zero 错误。

            public static string LinkifyYoutube(this string url)
            {
                if (!url.Contains("data-linkified"))
                {
                    return "";
                }
        
                int pos1 = url.IndexOf("<a target=\'_blank\' data-linkified href=\'", StringComparison.Ordinal);
                int pos2 = url.IndexOf("</a>", StringComparison.Ordinal);
        
                if (pos1 <= -1 || pos2 - pos1 <= 0)
                {
                    return "";
                }
        
                url = url.Substring(pos1, pos2 - pos1);
                url = url.Replace("<a target=\'_blank\' data-linkified href=\'", "");
                url = url.Replace("\'>", "");
                url = url.Replace("</a>", "");
        
                var zh = url.LastIndexOf("https", StringComparison.Ordinal);
        
                if (zh <= 0)
                {
                    return "";
                }
        
                url = url.Substring(0, zh);
        
                Uri uri = null;
                if (!Uri.TryCreate(url, UriKind.Absolute, out uri))
                {
                    try
                    {
                        uri = new UriBuilder("http", url).Uri;
                    }
                    catch
                    {
                        return "";
                    }
                }
        
                string host = uri.Host;
                string[] youTubeHosts = { "www.youtube.com", "youtube.com", "youtu.be", "www.youtu.be" };
                if (!youTubeHosts.Contains(host))
                {
                    return "";
                }
        
                var query = HttpUtility.ParseQueryString(uri.Query);
        
                if (query.AllKeys.Contains("v"))
                {
                    return Regex.Match(query["v"], @"^[a-zA-Z0-9_-]{11}$").Value;
                }
                else if (query.AllKeys.Contains("u"))
                {
                    return Regex.Match(query["u"], @"/watch\?v=([a-zA-Z0-9_-]{11})").Groups[1].Value;
                }
                else
                {
                    var last = uri.Segments.Last().Replace("/", "");
                    if (Regex.IsMatch(last, @"^v=[a-zA-Z0-9_-]{11}$"))
                    {
                        return last.Replace("v=", "");
                    }
        
                    string[] segments = uri.Segments;
                    if (segments.Length > 2 && segments[segments.Length - 2] != "v/" && segments[segments.Length - 2] != "watch/")
                    {
                        return "";
                    }
        
                    return Regex.Match(last, @"^[a-zA-Z0-9_-]{11}$").Value;
                }
            }
        

        【讨论】:

          猜你喜欢
          • 2019-10-24
          • 1970-01-01
          • 1970-01-01
          • 2018-12-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-02
          • 1970-01-01
          相关资源
          最近更新 更多