【问题标题】:Regex to match Youtube URL's正则表达式匹配 Youtube URL
【发布时间】:2010-09-17 17:40:39
【问题描述】:

我正在尝试使用正则表达式验证 Youtube URL:

preg_match('~http://youtube.com/watch\?v=[a-zA-Z0-9-]+~', $videoLink)

它有点工作,但它可以匹配格式错误的 URL。例如,这将匹配 ok:

http://www.youtube.com/watch?v=Zu4WXiPRek

但是这样也可以:

http://www.youtube.com/watch?v=Zu4WX£&P!ek

这不会:

http://www.youtube.com/watch?v=!Zu4WX£&P4ek

我认为这是因为 + 运算符。它匹配似乎是v= 之后的第一个字符,当它需要尝试将v= 后面的所有内容与[a-zA-Z0-9-] 匹配时。任何帮助表示赞赏,谢谢。

【问题讨论】:

  • 你所拥有的看起来不错。是£, & ! YouTube 字符串中的有效字符?如果是这样,请将它们添加到您的 [a-zA-Z0-9-] char 类中,否则,它是否按预期工作?
  • + 顺便说一句,意思是:匹配以下任何字符:[a-zA-Z0-9-] 一次或多次,所以它会一直运行,直到碰到不存在的东西。跨度>
  • 像这样的 Youtube 视频 ID 中允许的唯一字符是 a-z、A-Z、0-9 和 -。因此我为什么放[a-zA-Z0-9-]。它没有按预期工作。我可以提交如下 URL:v=Zu4WX£&P!ek(在这种情况下 £、& 和 ! 是非法字符)并且它可以很好地匹配它们,因为它只检查 v= 之后的第一个字符。
  • 如果您提供更多背景信息会有所帮助。你从哪里得到网址?是从整页抓取中获取的,并且 URL 位于 href="..." 中吗?你可以像 [a-zA-Z0-9-]+("|') 那样做你已经解析并循环遍历它们的 url 列表了吗?
  • 该 URL 是由用户通过表单提交的,在我向该页面发送请求之前,我需要检查它是否是一个有效的 Youtube URL。

标签: php regex youtube


【解决方案1】:

提供一个比正则表达式更大且不那么优雅的替代方案,但可以与 PHP 的原生 URL 解析函数一起使用,因此从长远来看它可能会更可靠:

 $url = "http://www.youtube.com/watch?v=Zu4WXiPRek";

 $query_string = parse_url($url, PHP_URL_QUERY); // v=Zu4WXiPRek

 $query_string_parsed = array();                        
 parse_str($query_string, $query_string_parsed); // an array with all GET params

 echo($query_string_parsed["v"]); // Will output Zu4WXiPRek that you can then
                                  // validate for [a-zA-Z0-9] using a regex

【讨论】:

  • 只是想指出,这只有在您已经拥有 url 时才真正有用(并且 IMO 推荐)......但如果他正在为 url 抓取页面......
  • 这似乎是添加代码回到原来的问题。问题在于验证v= 之后的字符串,这是这段代码提取的内容。我不需要提取它,我只需要确保 v= 之后的 URL 的其余部分与 [a-zA-Z0-9-] 匹配。
  • @Will 是的。这是一种更符合标准的方式,可以在一定程度上处理不断变化的 URL 结构。例如,当 URL 具有流行的 &fmt=18 参数时,它不会中断。无论如何,这只是一个替代建议;据我所知,@lonesomeday 回答了你的具体问题
【解决方案2】:

问题在于您不需要在 URL 的 v= 部分中包含任何特定数量的字符。因此,例如,检查

http://www.youtube.com/watch?v=Zu4WX£&P!ek

将匹配

http://www.youtube.com/watch?v=Zu4WX

因此返回true。您需要在 v= 部分指定所需的字符数:

preg_match('~http://youtube.com/watch\?v=[a-zA-Z0-9-]{10}~', $videoLink)

或指定组 [a-zA-Z0-9-] 必须是字符串的最后一部分:

preg_match('~http://youtube.com/watch\?v=[a-zA-Z0-9-]+$~', $videoLink)

你的另一个例子

http://www.youtube.com/watch?v=!Zu4WX£&P4ek

不匹配,因为 + 号要求至少有一个字符必须匹配 [a-zA-Z0-9-]。

【讨论】:

  • 我很确定 v= 部分会有所不同,这就是为什么我之前没有使用它......并且使用 [a-zA-Z0-9-]$ 也不起作用。它只是为所有内容返回 false。
  • 那是因为它应该是:[a-zA-Z0-9-]+$ 只是一个错字。
【解决方案3】:

简答:

preg_match('%(@987654321@\?v=(?:[a-zA-Z0-9-])+)(?:[&"\'\s])%', $videoLink)

这里做了一些假设,所以让我解释一下:

  • 我在链接的整个 @987654322@ 部分周围添加了一个捕获组 ( ... ),这样我们就可以说“我希望获得整个经过验证的链接,包括 ?v=movieHash”
  • 我在您的字符集[a-zA-Z0-9-] 周围添加了非捕获组(?: ... ),并将+ 号留在了该组之外。这将允许我们匹配所有允许的字符直到某个点。
  • 最重要的是,您需要告诉它您希望您的链接如何终止。我用(?:[&"\'\s])为你猜一猜

    ?) 会是 html 格式(例如锚标签)吗?如果是这样,href 中的链接显然会以 "' 结尾。
    ?) 或者查询字符串可能还有更多内容,因此在 v 的值之后会有一个 &
    ?) 链接结束后可能有空格或换行符\s

重要的是,如果您知道要搜索的内容周围的内容,您可以获得更准确的结果,就像许多正则表达式一样。

这个非捕获组(我在其中为您做出假设)将努力寻找并忽略您关心的所有额外垃圾(?v=awesomeMovieHash) .

结果:

http://www.youtube.com/watch?v=Zu4WXiPRek
 - Group 1 contains the http://www.youtube.com/watch?v=Zu4WXiPRek

http://www.youtube.com/watch?v=Zu4WX&a=b
 - Group 1 contains http://www.youtube.com/watch?v=Zu4WX

http://www.youtube.com/watch?v=!Zu4WX£&P4ek
 - No match

a href="http://www.youtube.com/watch?v=Zu4WX&size=large"
 - Group 1 contains http://www.youtube.com/watch?v=Zu4WX

http://www.youtube.com/watch?v=Zu4WX£&P!ek
 - No match

【讨论】:

    【解决方案4】:

    “v=...”blob 不能保证是 URL 查询部分的第一个参数。我建议使用 PHP 的 parse_url() 函数将 URL 分解为其组成部分。如果有人以“https://”开头的字符串或简单地使用“youtube.com”而不是“www.youtube.com”等,您还可以重新组合一个原始 URL。

    function get_youtube_vidid ($url) {
        $vidid = false;
        $valid_schemes = array ('http', 'https');
        $valid_hosts = array ('www.youtube.com', 'youtube.com');
        $valid_paths = array ('/watch');
    
        $bits = parse_url ($url);
        if (! is_array ($bits)) {
            return false;
        }
        if (! (array_key_exists ('scheme', $bits)
                and array_key_exists ('host', $bits)
                and array_key_exists ('path', $bits)
                and array_key_exists ('query', $bits))) {
            return false;
        }
        if (! in_array ($bits['scheme'], $valid_schemes)) {
            return false;
        }
        if (! in_array ($bits['host'], $valid_hosts)) {
            return false;
        }
        if (! in_array ($bits['path'], $valid_paths)) {
            return false;
        }
        $querypairs = explode ('&', $bits['query']);
        if (count ($querypairs) < 1) {
            return false;
        }
        foreach ($querypairs as $querypair) {
            list ($key, $value) = explode ('=', $querypair);
            if ($key == 'v') {
                if (preg_match ('/^[a-zA-Z0-9\-_]+$/', $value)) {
                    # Set the return value
                    $vidid = $value;
                }
            }
        }
    
        return $vidid;
    }
    

    【讨论】:

      【解决方案5】:

      以下正则表达式将匹配任何 youtube 链接:

      $pattern='@(((http(s)?://(www\.)?)|(www\.)|\s)(youtu\.be|youtube\.com)/(embed/|v/|watch(\?v=|\?.+&v=|/))?([a-zA-Z0-9._\/~#&=;%+?-\!]+))@si';
      

      【讨论】:

      • 它不适用于youtube-nocookie.com URL,也不适用于带有?v=0123456789a&amp;q=18#t=12s 之类的查询字符串的URL。
      • 另外,你的角色类有一个倒置的类范围?-\。这意味着它不适用于许多正则表达式风格,包括 PHP preg。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-19
      • 2015-09-14
      • 2021-12-31
      相关资源
      最近更新 更多