如何使用正则表达式在字符串中查找所有 YouTube 视频 ID?

Posted

技术标签:

【中文标题】如何使用正则表达式在字符串中查找所有 YouTube 视频 ID?【英文标题】:How do I find all YouTube video ids in a string using a regex? 【发布时间】:2011-08-15 09:09:42 【问题描述】:

我有一个文本字段,用户可以在其中写任何东西。

例如:

Lorem Ipsum 只是虚拟文本。 http://www.youtube.com/watch?v=DUQi_R4SgWo 印刷和排版的 行业。 Lorem Ipsum 一直是 业界标准的虚拟文本 自 1500 年代以来,当一个未知的 打印机拿了一个类型的厨房和 把它炒作一个类型标本 书。它不仅存活了五 百年,也跃进 电子排版,剩余 基本不变。 http://www.youtube.com/watch?v=A_6gNZCkajU&feature=relmfu 它在 1960 年代流行于 Letraset 表的发布 包含 Lorem Ipsum 段落,以及 最近与桌面出版 像 Aldus PageMaker 这样的软件 包括 Lorem Ipsum 的版本。

现在我想解析它并找到所有 YouTube 视频 URL 及其 ID。

知道它是如何工作的吗?

【问题讨论】:

javascript REGEX: How to get youtube video id from URL?的可能重复 【参考方案1】:

可能会遇到多种格式的 YouTube 视频 URL:

最新短格式:http://youtu.be/NLqAF9hrVbY iframe:http://www.youtube.com/embed/NLqAF9hrVbY iframe(安全):https://www.youtube.com/embed/NLqAF9hrVbY 对象参数:http://www.youtube.com/v/NLqAF9hrVbY?fs=1&hl=en_US 对象嵌入:http://www.youtube.com/v/NLqAF9hrVbY?fs=1&hl=en_US 观看:http://www.youtube.com/watch?v=NLqAF9hrVbY 用户:http://www.youtube.com/user/Scobleizer#p/u/1/1p3vcRhsYGo yt 放映室:http://www.youtube.com/ytscreeningroom?v=NRHVzbJVx8I 任何/事情/去!:http://www.youtube.com/sandalsResorts#p/c/54B8C800269D7C1B/2/PPS-8DMrAn4 任何/子域/也:http://gdata.youtube.com/feeds/api/videos/NLqAF9hrVbY 更多参数:http://www.youtube.com/watch?v=spDj54kf-vY&feature=g-vrec 查询可能有点:http://www.youtube.com/watch?v=spDj54kf-vY&feature=youtu.be nocookie 域:http://www.youtube-nocookie.com

这是一个带有注释正则表达式的 php 函数,它匹配每个 URL 形式并将它们转换为链接(如果它们还不是链接):

// Linkify youtube URLs which are not already links.
function linkifyYouTubeURLs($text) 
    $text = preg_replace('~(?#!js YouTubeId Rev:20160125_1800)
        # Match non-linked youtube URL in the wild. (Rev:20130823)
        https?://          # Required scheme. Either http or https.
        (?:[0-9A-Z-]+\.)?  # Optional subdomain.
        (?:                # Group host alternatives.
          youtu\.be/       # Either youtu.be,
        | youtube          # or youtube.com or
          (?:-nocookie)?   # youtube-nocookie.com
          \.com            # followed by
          \S*?             # Allow anything up to VIDEO_ID,
          [^\w\s-]         # but char before ID is non-ID char.
        )                  # End host alternatives.
        ([\w-]11)        # $1: VIDEO_ID is exactly 11 chars.
        (?=[^\w-]|$)       # Assert next char is non-ID or EOS.
        (?!                # Assert URL is not pre-linked.
          [?=&+%\w.-]*     # Allow URL (query) remainder.
          (?:              # Group pre-linked alternatives.
            [\'"][^<>]*>   # Either inside a start tag,
          | </a>           # or inside <a> element text contents.
          )                # End recognized pre-linked alts.
        )                  # End negative lookahead assertion.
        [?=&+%\w.-]*       # Consume any URL (query) remainder.
        ~ix', '<a href="http://www.youtube.com/watch?v=$1">YouTube link: $1</a>',
        $text);
    return $text;

; // 结束 $YouTubeId。

这是一个 JavaScript 版本,其正则表达式完全相同(删除了 cmets):

// Linkify youtube URLs which are not already links.
function linkifyYouTubeURLs(text) 
    var re = /https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube(?:-nocookie)?\.com\S*?[^\w\s-])([\w-]11)(?=[^\w-]|$)(?![?=&+%\w.-]*(?:['"][^<>]*>|<\/a>))[?=&+%\w.-]*/ig;
    return text.replace(re,
        '<a href="http://www.youtube.com/watch?v=$1">YouTube link: $1</a>');

注意事项:

URL 的 VIDEO_ID 部分在唯一的捕获组中捕获:$1。 如果您知道您的文本不包含任何预链接的 URL,则可以安全地删除测试此条件的否定前瞻断言(以注释开头的断言:“断言 URL 未预链接.") 这将在一定程度上加快正则表达式的速度。 可以修改替换字符串以适合。上面提供的只是创建一个指向通用 "http://www.youtube.com/watch?v=VIDEO_ID" 样式 URL 的链接,并将链接文本设置为:"YouTube link: VIDEO_ID"

2011-07-05 编辑:在 ID char 类中添加了- 连字符

2011 年 7 月 17 日编辑: 修复了正则表达式以使用 YouTube ID 后面的 URL 的任何剩余部分(例如 查询)。添加了'i' ignore-case 修饰符。将函数重命名为 camelCase。改进了预链接的前瞻测试。

2011 年 7 月 27 日编辑:添加了新的 YouTube 网址“用户”和“ytscreeningroom”格式。

2011-08-02 编辑:简化/通用化以处理新的“any/thing/goes”YouTube URL。

编辑 2011-08-25: 几处修改:

添加了 Javascript 版本:linkifyYouTubeURLs() 函数。 先前版本的方案(HTTP 协议)部分是可选的,因此会匹配无效的 URL。使方案部分成为必需的。 以前的版本在 VIDEO_ID 周围使用了\b 字边界锚。但是,如果 VIDEO_ID 以 - 破折号开头或结尾,这将不起作用。已修复,以便处理这种情况。 更改了 VIDEO_ID 表达式,使其长度必须正好为 11 个字符。 如果 VIDEO_ID 后面有查询字符串,则以前的版本无法排除预链接 URL。改进了否定前瞻断言以解决此问题。 在字符类匹配查询字符串中添加了+%。 将 PHP 版本正则表达式分隔符从:% 更改为:~。 添加了带有一些方便注释的“注释”部分。

编辑 2011-10-12:YouTube URL 主机部分现在可以有任何子域(不仅仅是www.)。

编辑 2012-05-01:使用 URL 部分现在可以允许使用“-”。

2013-08-23 编辑:添加了@Mei 提供的附加格式。 (查询部分可能有一个. 点。

2013-11-30 编辑:添加了@CRONUS 提供的其他格式:youtube-nocookie.com

编辑 2016-01-25: 修复了正则表达式以处理 CRONUS 提供的错误情况。

【讨论】:

我还没有看到规范,但我确实搜索了一个。我刚刚注意到互联网上一些链接中的破折号。例如:youtube.com/watch?v=CLPk-6_xgiY @littleFluffyKitty:感谢您的提醒。已更新答案以包含连字符作为有效的 ID 字符。 @ridgerunner:如果您对编辑没有信心,可以回滚。此外,就像在***上一样,整个历史都与您的学分一起保存。随着时间的推移,我看到你真的很喜欢答案,所以把你丢在这里太可惜了。 这是一个不起作用的方法:youtube.com/watch?v=E1IPnnttL9k&feature=youtu.be 这很好用,但是这个(新的?)查询字符串参数失败了:feature=youtu.be。将 [?=&+%\w-]* 更改为 [?=&+%\w-\.]* 在“使用剩余 url”行上就可以了。谢谢!【参考方案2】:

这是我曾经为一个提取 YouTube 和 Vimeo 视频密钥的项目编写的方法:

/**
 *  strip important information out of any video link
 *
 *  @param  string  link to a video on the hosters page
 *  @return mixed  FALSE on failure, array on success
 */
function getHostInfo ($vid_link)

  // YouTube get video id
  if (strpos($vid_link, 'youtu'))
  
    // Regular links
    if (preg_match('/(?<=v\=)([\w\d-_]+)/', $vid_link, $matches))
      return array('host_name' => 'youtube', 'original_key' => $matches[0]); 
    // Ajax hash tag links
    else if (preg_match('§([\d\w-_]+)$§i', $vid_link, $matches))
      return array('host_name' => 'youtube', 'original_key' => $matches[0]);
    else
      return FALSE;
  
  // Vimeo get video id
  elseif (strpos($vid_link, 'vimeo'))
  
    if (preg_match('§(?<=/)([\d]+)§', $vid_link, $matches))
      return array('host_name' => 'vimeo', 'original_key' => $matches[0]); 
    else
      return FALSE;
  
  else
    return FALSE;

    查找将从文本中提取所有链接的正则表达式。 Google 会在这方面为您提供帮助。 循环所有链接并为每个链接调用 getHostInfo()

【讨论】:

非常感谢!轻微的 mod if(strpos($vid_link, 'youtu')) 将捕获除了常见 url 之外的短 url youtu.be 不客气。感谢您的更新,我在更改中进行了编辑。在旁注中,ridgerunner 的正则表达式似乎是真正的交易,我建议在我的简单事情上使用它。欢呼 正是我想要的。看准队友! +1【参考方案3】:

虽然 ridgerunner 的回答是我回答的基础,但他并不能解决所有网址,而且我不相信它能够解决,因为 YouTube 网址中有多个可能匹配的 VIDEO_ID。我的正则表达式将他的激进方法作为最后的手段,但首先尝试所有常见的匹配,从而大大降低了 URL 稍后出现错误匹配的可能性。

这个正则表达式:

/https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube\.com(?:\/embed\/|\/v\/|\/watch\?v=|\/ytscreeningroom\?v=|\/feeds\/api\/videos\/|\/user\S*[^\w\-\s]|\S*[^\w\-\s]))([\w\-]11)[?=&+%\w-]*/ig;

处理最初在 ridgerunners 示例中引用的所有情况,以及在 url 后面可能碰巧有 11 个字符序列的任何 url。即:

http://www.youtube.com/watch?v=GUEZCxBcM78&feature=pyv&feature=pyv&ad=10059374899&kw=%2Bwingsuit

这是一个测试所有示例 YouTube 网址的工作示例:

http://jsfiddle.net/DJSwc/5/

【讨论】:

【参考方案4】:

试试

[^\s]*youtube\.com[^\s]*?v=([-\w]+)[^\s]*

您将在第一个捕获组中找到视频 ID。我不知道什么是有效的视频 ID?目前我检查v= 并捕获所有-A-Za-z0-9_

我使用您的示例字符串在线检查了here on rubular。

【讨论】:

【参考方案5】:

用途:

<?php

    // The YouTube URL string

    $youtube_url='http://www.youtube.com/watch?v=8VtUYvwktFQ';

    // Use regex to get the video ID

    $regex='#(?<=v=)[a-zA-Z0-9-]+(?=&)|(?<=[0-9]/)[^&\n]+|(?<=v=)[^&\n]+#';

    preg_match($regex, $youtube_url, $id);

    // Plug that into our html
?>

【讨论】:

【参考方案6】:

好的,我自己做了一个函数。但我认为这是非常低效的。 欢迎任何改进:

function get_youtube_videos($string) 

    $ids = array();

    // Find all URLs
    preg_match_all('/(http|https)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]2,3(\/\S*)?/', $string, $links);

    foreach ($links[0] as $link) 
        if (preg_match('~youtube\.com~', $link)) 
            if (preg_match('/[^=]+=([^?]+)/', $link, $id)) 
                $ids[] = $id[1];
            
        
    
    return $ids;

【讨论】:

如果您只寻找来自 youtube.com 的链接,为什么要首先建立一个包含所有链接的列表?而且我认为没有必要使用 3 种不同的正则表达式。【参考方案7】:

我尝试了一个简单的表达式来只获取videoid:

[?&]v=([^&#]*)

在线查看here at phpliveregex。

【讨论】:

【参考方案8】:

原发帖人问“我想解析它并找到所有 YouTube 视频 URL 及其 ID。”我将上面最受欢迎的答案切换为 preg_match 并返回了视频 ID 和 URL。

从帖子中获取 YouTube URL 和 ID:

$match[0] = Full URL
$match[1] = video ID

function get_youtube_id($input) 
    $input = preg_match('~https?://(?:[0-9A-Z-]+\.)?(?:youtu\.be/|youtube(?:-nocookie)?\.com\S*[^\w\s-])([\w-]11)(?=[^\w-]|$)(?![?=&+%\w.-]*(?:[\'"][^<>]*>|</a>))[?=&+%\w.-]*~ix',
                        $input, $match);
    return $match;

【讨论】:

【参考方案9】:

从字符串中轻松找到 YouTube 链接:

function my_url_search($se_action_data)

    $regex = '/https?\:\/\/[^\" ]+/i';
    preg_match_all($regex, $se_action_data, $matches);
    $get_url=array_reverse($matches[0]);
    return array_unique($get_url);

echo my_url_search($se_action_data)

【讨论】:

这不仅适用于 YoutTube,它还会匹配内容中的其他 url。【参考方案10】:
String urlid="" ;
String  url="http://www.youtube.com/watch?v=0zM4nApSvMg#t=0m10s";
Pattern pattern =Pattern.compile("(?:http|https|)(?::\\/\\/|)(?:www.|)(?:youtu\\.be\\/|youtube\\.com(?:\\/embed\\/|\\/v\\/|\\/watch\\?v=|\\/ytscreeningroom\\?v=|\\/feeds\\/api\\/videos\\/|\\/user\\\\S*[^\\w\\-\\s]|\\S*[^\\w\\-\\s]))([\\w\\-\\_]11)[a-z0-9;:@#?&%=+\\/\\$_.-]*");
Matcher result = pattern.matcher(url);
    if (result.find())
    
         urlid=result.group(1);

    

Java 中的这段代码对目前所有的 youtube 网址都适用。

【讨论】:

以上是关于如何使用正则表达式在字符串中查找所有 YouTube 视频 ID?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JS 正则表达式查找所有不匹配字符的索引?

如何创建正则表达式来查找 JS 文件(或 JSON)中的所有字符串

如何使用正则表达式在字符串表达式中查找以@开头的变量名?

如何使用正则表达式查找具有特定起始字符串的所有匹配项? [复制]

如何使用正则表达式和 Notepad++ 删除所有非 ASCII 字符?

正则表达式查找所有子字符串和最长的子字符串