使用正则表达式验证 Youtube URL

问题描述 投票:0回答:6

我正在尝试验证我的应用程序的 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 网址的以下变体:

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

但是,我认为我的逻辑不正确,因为由于某种原因,它返回 true 为:

www.youtube.co/watch?v=vpfzjcCzdtCk
(请注意,我用
.co
而不是
.com
写错了)

php regex youtube
6个回答
39
投票

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

$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> )
    。这使得表达更加高效。

可选地,要从(或多或少完整的)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。


5
投票

正则表达式的替代方案是

parse_url()

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

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


4
投票

请尝试:

// 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";
}

你有||无论如何,没有 ^$ 也没关系。


3
投票

我遵循本页上的其他答案来解析 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 个字符 的字符串长度。在这种情况下,输出能够编码

22 × 6 = 132
位,剩余 4 位;这些零最终限制了 64 个字母符号中的大部分出现在最后一个位置,只有 4 个仍然符合条件。所有 channelId 字符串均以以下之一结尾:

{ A, Q, g, w }

这为我们提供了 channelId:

的正则表达式
[-_A-Za-z0-9]{21}[AQgw]

3
投票

这应该可以做到:

$valid = preg_match("/^(https?\:\/\/)?(www\.)?(youtube\.com|youtu\.be)\/watch\?v\=\w+$/", $youtube_url);
if ($valid) {
    echo "Valid";
} else {
    echo "Invalid";
}

0
投票

如果您想涵盖所有变体,请查看:

^(?:(?:https?:)?\/\/)?(?:(?:(?:www|m(?:usic)?)\.)?youtu(?:\.be|be(?:-nocookie)?\.com))\/(?:shorts\/|live\/|v\/|e(?:mbed)?\/|watch(?:\/|\?(?:\S+=\S+&)*v=)|oembed\?url=https?%3A\/\/(?:www|m(?:usic)?)\.youtube(?:-nocookie)?\.com\/watch\?(?:\S+=\S+&)*v%3D|attribution_link\?(?:\S+=\S+&)*u=(?:\/|%2F)watch(?:\?|%3F)v(?:=|%3D)|playlist\?(?:\S+=\S+&)*list=)?([\w-]+)[\?&#]?\S*$

这是来自相关问题的正则表达式。从任何已知的 YouTube URL(还有 music.*、shorts/、live/、e/ embed/、v/、*-nocookie 等)中提取视频 ID。

如果需要,您可以在正则表达式中使用

{11}
而不是
+
将视频 ID 限制为 11 个字符。或者用格伦的回答

© www.soinside.com 2019 - 2024. All rights reserved.