18

我正在尝试验证我的应用程序的 YouTube 网址。

到目前为止,我有以下内容:

// Set the youtube URL
$youtube_url = "www.youtube.com/watch?v=vpfzjcCzdtCk";

if (preg_match("/((http\:\/\/){0,}(www\.){0,}(youtube\.com){1} || (youtu\.be){1}(\/watch\?v\=[^\s]){1})/", $youtube_url) == 1)
{
    echo "Valid";
else
{
    echo "Invalid";
}

我希望验证以下 Youtube Urls 变体:

  • 有和没有 http://
  • 有和没有 www。
  • 使用网址 youtube.com 和 youtu.be
  • 必须有 /watch?v=
  • 必须具有唯一的视频字符串(在上面的示例中为“vpfzjcCzdtCk”)

但是,我认为我的逻辑不正确,因为由于某种原因它返回true为:(www.youtube.co/watch?v=vpfzjcCzdtCk注意我用.coand not写错了.com

4

5 回答 5

38

你的这个正则表达式有很多冗余(还有倾斜牙签综合症)。但是,这应该会产生结果:

$rx = '~
  ^(?:https?://)?                           # Optional protocol
   (?:www[.])?                              # Optional sub-domain
   (?:youtube[.]com/watch[?]v=|youtu[.]be/) # Mandatory domain name (w/ query string in .com)
   ([^&]{11})                               # Video id of 11 characters as capture group 1
    ~x';

$has_match = preg_match($rx, $url, $matches);

// if matching succeeded, $matches[1] would contain the video ID

一些注意事项:

  • 使用波浪号~作为分隔符,以避免 LTS
  • 使用[.]而不是\.提高视觉易读性并避免 LTS。(“特殊”字符 - 例如点.- 在字符类中无效(在方括号内))
  • 要使正则表达式更“可读”,您可以使用x修饰符(这具有进一步的含义;请参阅有关 Pattern 修饰符的文档),它还允许在正则表达式中添加注释
  • 可以使用非捕获组来抑制捕获:(?: <pattern> ). 这使得表达更有效。

或者,要从(或多或少完整的)URL 中提取值,您可能需要使用parse_url()

$url = 'http://youtube.com/watch?v=VIDEOID';
$parts = parse_url($url);
print_r($parts);

输出:

Array
(
    [scheme] => http
    [host] => youtube.com
    [path] => /watch
    [query] => v=VIDEOID
)

验证域名和提取视频 ID 作为练习留给读者。


我屈服于下面的评论战;感谢 Toni Oriol,正则表达式现在也适用于短 (youtu.be) URL。

于 2012-11-20T15:13:43.930 回答
5

正则表达式的替代方法是parse_url().

 $parts = parse_url($url);
 if ($parts['host'] == 'youtube.com' && ...) {
   // your code
 }

虽然它是更多代码,但它更具可读性,因此更易于维护。

于 2012-11-20T15:15:20.790 回答
3

这应该这样做:

$valid = preg_match("/^(https?\:\/\/)?(www\.)?(youtube\.com|youtu\.be)\/watch\?v\=\w+$/", $youtube_url);
if ($valid) {
    echo "Valid";
} else {
    echo "Invalid";
}
于 2012-11-20T15:11:43.080 回答
3

请试试:

// Set the youtube URL
$youtube_url = "www.youtube.com/watch?v=vpfzjcCzdtCk";

if (preg_match("/^((http\:\/\/){0,}(www\.){0,}(youtube\.com){1}|(youtu\.be){1}(\/watch\?v\=[^\s]){1})$/", $youtube_url) == 1)
{
    echo "Valid";
}
else
{
    echo "Invalid";
}

你有|| 在任何情况下没有 ^$ 都可以。

于 2012-11-20T15:09:25.180 回答
2

我遵循此页面上的其他答案来解析 URL 语法,但对于YouTube ID值本身,您可以更具体一点,正如我在StackExchange/WebApps上的以下答案中所描述的那样:

YouTube 视频 ID 的格式   -    https://webapps.stackexchange.com/a/101153/141734


视频 ID

对于videoId,它是一个 8 字节(64 位)整数。对 8 个字节的数据应用 Base64 编码需要11 个字符。但是,由于每个 Base64 字符恰好传达 6 位,因此这种分配实际上可以容纳11 × 6 = 66位 - 比我们的有效负载需要的多 2 位。多余的位设置为零,这具有排除某些字符出现在编码字符串的最后位置的效果。特别是,videoId将始终以下列之一结尾:

{ A, E, I, M, Q, U, Y, c, g, k, o, s, w, 0, 4, 8 }

因此,videoId的正则表达式 (RegEx)如下所示:

[-_A-Za-z0-9]{10}[AEIMQUYcgkosw048]

频道或播放列表 ID

channelIdplaylistId字符串是通过Base64 编码 128 位(16 字节)二进制整数生成的。同样在这里,每个 Base64 的计算正确地预测了观察到的22-characters字符串长度。在这种情况下,输出能够编码22 × 6 = 132位,剩余4位;这些零最终限制了 64 个字母符号中的大多数出现在最后一个位置,只有 4 个仍然符合条件。所有channelId字符串都以下列之一结尾:

{ A, Q, g, w }

这为我们提供了channelId的正则表达式:

[-_A-Za-z0-9]{21}[AQgw]
于 2017-02-01T19:41:20.163 回答