从任何YouTube URL中获取YouTube视频ID的正则表达式模式

10

让我们拿这些网址作为例子:

  1. http://www.youtube.com/watch?v=8GqqjVXhfMU&feature=youtube_gdata_player
  2. http://www.youtube.com/watch?v=8GqqjVXhfMU

这个PHP函数在情况1中将无法正确获取ID,但在情况2中可以。情况1非常普遍,在YouTube ID之后可以加上任何东西。

/**
 * get YouTube video ID from URL
 *
 * @param string $url
 * @return string YouTube video id or FALSE if none found. 
 */
function youtube_id_from_url($url) {
    $pattern = 
        '%^# Match any YouTube URL
        (?:https?://)?  # Optional scheme. Either http or https
        (?:www\.)?      # Optional www subdomain
        (?:             # Group host alternatives
          youtu\.be/    # Either youtu.be,
        | youtube\.com  # or youtube.com
          (?:           # Group path alternatives
            /embed/     # Either /embed/
          | /v/         # or /v/
          | /watch\?v=  # or /watch\?v=
          )             # End path alternatives.
        )               # End host alternatives.
        ([\w-]{10,12})  # Allow 10-12 for 11 char YouTube id.
        $%x'
        ;
    $result = preg_match($pattern, $url, $matches);
    if (false !== $result) {
        return $matches[1];
    }
    return false;
}

我在思考的是是否有一种方法可以只查找“v =”,无论它在URL中的位置如何,然后获取其后面的字符。用这种方式,就不需要使用复杂的正则表达式了。这种想法是否正确?有没有起点的想法?


我认为这个模式的主要问题就是模式末尾的 $,它将模式锚定在正在测试的字符串的末尾。这就是为什么 Case 1 不匹配的原因,因为它没有以 ID 结尾。 - Bendoh
9个回答

30
if (preg_match('/youtube\.com\/watch\?v=([^\&\?\/]+)/', $url, $id)) {
  $values = $id[1];
} else if (preg_match('/youtube\.com\/embed\/([^\&\?\/]+)/', $url, $id)) {
  $values = $id[1];
} else if (preg_match('/youtube\.com\/v\/([^\&\?\/]+)/', $url, $id)) {
  $values = $id[1];
} else if (preg_match('/youtu\.be\/([^\&\?\/]+)/', $url, $id)) {
  $values = $id[1];
}
else if (preg_match('/youtube\.com\/verify_age\?next_url=\/watch%3Fv%3D([^\&\?\/]+)/', $url, $id)) {
    $values = $id[1];
} else {   
// not an youtube video
}

这是我用来从YouTube链接中提取视频id的方法。我认为它适用于所有情况。

请注意,最后$values =视频的id。


1
这更为通用,可以捕获从 / 到 YouTube 得到的各种 URL 形式。+1 - Bendoh
@Bendoh为什么这个比使用parse_str选择的答案更通用 - parse_str似乎可以完美地捕获URL中的每个变量? - Shackrock
1
所选答案不会捕获形式为/v/<id>或embed/<id>的URL,只会捕获包含查询参数“v”的形式。它也不会注意链接的主机名 - 它只会从任何具有查询字符串中的“v”参数的URL中提取“v”的值。例如,http://www.youtube.com/v/ihCbVT637aM 将无法正确解析。 - Bendoh
@Bendoh - 你说得对...谢谢。我已经将其更改为“最佳答案”。 - Shackrock
有人知道 JavaScript 的等效物吗? - newton_guima

9

不要使用正则表达式,我强烈建议使用 parse_url()parse_str()

$url = "http://www.youtube.com/watch?v=8GqqjVXhfMU&feature=youtube_gdata_player";
parse_str(parse_url( $url, PHP_URL_QUERY ), $vars );
echo $vars['v'];    

完成


2
你可以使用 parse_urlparse_str 函数来实现这个功能:
$query_string = parse_url($url, PHP_URL_QUERY);
parse_str($query_string);
echo $v;

1

我使用以下模式,因为YouTube也有一个youtube-nocookie.com域:

'@youtube(?:-nocookie)?\.com/watch[#\?].*?v=([^"\& ]+)@i',
'@youtube(?:-nocookie)?\.com/embed/([^"\&\? ]+)@i',
'@youtube(?:-nocookie)?\.com/v/([^"\&\? ]+)@i',
'@youtube(?:-nocookie)?\.com/\?v=([^"\& ]+)@i',
'@youtu\.be/([^"\&\? ]+)@i',
'@gdata\.youtube\.com/feeds/api/videos/([^"\&\? ]+)@i',

在您的情况下,这只意味着使用可选项“-nocookie”来扩展现有表达式,用于常规的YouTube.com URL,如下所示:
if (preg_match('/youtube(?:-nocookie)\.com\/watch\?v=([^\&\?\/]+)/', $url, $id)) {

如果您将建议的表达式更改为不包含最后一个$,它应该按照您预期的方式工作。我也添加了-nocookie。
/**
 * get YouTube video ID from URL
 *
 * @param string $url
 * @return string YouTube video id or FALSE if none found. 
 */
function youtube_id_from_url($url) {
    $pattern = 
        '%^# Match any YouTube URL
        (?:https?://)?  # Optional scheme. Either http or https
        (?:www\.)?      # Optional www subdomain
        (?:             # Group host alternatives
          youtu\.be/    # Either youtu.be,
        |youtube(?:-nocookie)?\.com  # or youtube.com and youtube-nocookie
          (?:           # Group path alternatives
            /embed/     # Either /embed/
          | /v/         # or /v/
          | /watch\?v=  # or /watch\?v=
          )             # End path alternatives.
        )               # End host alternatives.
        ([\w-]{10,12})  # Allow 10-12 for 11 char YouTube id.
        %x'
        ;
    $result = preg_match($pattern, $url, $matches);
    if (false !== $result) {
        return $matches[1];
    }
    return false;
}

0
另一种简单的方法是使用parse_str()函数:
<?php
    $url = 'http://www.youtube.com/watch?v=8GqqjVXhfMU&feature=youtube_gdata_player';
    parse_str($url, $yt);

    // The associative array $yt now contains all of the key-value pairs from the querystring (along with the base 'watch' URL, but doesn't seem you need that)
    echo $yt['v']; // echos '8GqqjVXhfMU';
?>

看起来你缺少了 parse_url,正如其他答案所述。有了 parse_url 就可以工作了。FYI - Shackrock
不需要解析URL。有人认为这样更干净,但至少在PHP 5.3.6中,查询字符串参数之前的URL只是数组中的一个键。——编辑:啊该死,当只有一个QS参数时,这个方法可以工作,但函数必须在&上分割。parse_url会更正确。 - Morgon

0

parse_url的建议很好。如果你真的想用正则表达式,可以使用这个:

/(?<=v=)[^&]+/`

0

任何YouTube链接的解决方案:

http://youtube.com/v/dQw4w9WgXcQ
http://youtube.com/watch?v=dQw4w9WgXcQ
http://www.youtube.com/watch?feature=player&v=dQw4w9WgXcQ&var2=bla
http://youtu.be/dQw4w9WgXcQ

==

https://dev59.com/RXA75IYBdhLWcg3wRWoU#20614061


0

这里有一个解决方案

/**
 * credits goes to: http://stackoverflow.com/questions/11438544/php-regex-for-youtube-video-id
 * update: mobile link detection
 */
public function parseYouTubeUrl($url)
{
     $pattern = '#^(?:https?://)?(?:www\.)?(?:m\.)?(?:youtu\.be/|youtube\.com(?:/embed/|/v/|/watch\?v=|/watch\?.+&v=))([\w-]{11})(?:.+)?$#x';
     preg_match($pattern, $url, $matches);
     return (isset($matches[1])) ? $matches[1] : false;
}

它也可以处理移动链接。


-1
这是我用于检索Youtube ID的函数!
function getYouTubeId($url) {
    if (!(strpos($url, 'v=') !== false)) return false;
    $parse = explode('v=', $url);
    $code = $parse[1];
    if (strlen($code) < 11) return false;
    $code = substr($code, 0, 11);
    return $code;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接