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

n00*_*00b 91 php regex youtube

我有一个用户可以写任何东西的文本域.

例如:

Lorem Ipsum只是虚拟文本. http://www.youtube.com/watch?v=DUQi_R4SgWo 印刷和排版行业.自16世纪以来,Lorem Ipsum一直是业界标准的虚拟文本,当时一台未知的打印机采用了类型的厨房,并将其拼凑成一本类型的样本.它不仅存在了五个世纪,而且还延续了电子排版,基本保持不变. http://www.youtube.com/watch?v=A_6gNZCkajU&feature=relmfu 它在20世纪60年代推出了包含Lorem Ipsum段落的Letraset表格,最近还发布了包括Lorem Ipsum版本在内的Aldus PageMaker等桌面出版软件.

现在我想解析它并查找所有YouTube视频网址及其ID.

知道它是如何工作的吗?

rid*_*ner 287

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

  • 最新的短格式: 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
  • ytscreeningroom: 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;
}
Run Code Online (Sandbox Code Playgroud)

; //结束$ YouTubeId.

这是一个完全相同的正则表达式的JavaScript版本(删除了注释):

// 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>');
}
Run Code Online (Sandbox Code Playgroud)

笔记:

  • URL的VIDEO_ID部分在唯一的捕获组中捕获:$1.
  • 如果你知道你的文本中不包含任何预链接的网址,你可以安全地删除式断言测试对于此条件(断言开头的注释:"断言URL不预链接"),这将加速有点像正则表达式.
  • 替换字符串可以修改以适应.上面提供的那个只是创建了一个通用"http://www.youtube.com/watch?v=VIDEO_ID"样式URL的链接,并将链接文本设置为:"YouTube link: VIDEO_ID".

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

编辑2011-07-17:修复了正则表达式,以使用YouTube ID后面的URL的任何剩余部分(例如查询).添加了'i' ignore-case修饰符.将功能重命名为camelCase.改进了预先链接的先行测试.

编辑2011-07-27:添加了新的"用户"和"ytscreeningroom"格式的YouTube网址.

编辑2011-08-02:简化/概括以处理新的"任何/事物/去"YouTube网址.

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

  • 添加了Javascript版本的:linkifyYouTubeURLs()function.
  • 以前的版本使方案(HTTP协议)部分可选,因此将匹配无效的URL.使计划部分成为必需.
  • 以前的版本\b在VIDEO_ID周围使用了单词边界锚点.但是,如果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提供的错误案例.

  • 虽然我确实搜索了一个规格,但我还没有看到规格.我刚刚注意到互联网荒野中的一些链接.例如:http://www.youtube.com/watch?v = CLPk-6_xgiY (2认同)

Chr*_*tof 10

这是我曾经为一个提取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;
}
Run Code Online (Sandbox Code Playgroud)
  1. 找到一个将从文本中提取所有链接的正则表达式.谷歌会帮助你.
  2. 循环所有链接并为每个链接调用getHostInfo()


ezw*_*ter 8

尽管ridgerunner的答案是我答案的基础,但由于VIDEO_IDYouTube网址中存在多种可能的匹配,因此他并不能解决所有网址问题而且我认为它无法解决问题.我的正则表达式包括他作为最后手段的积极方法,但首先尝试所有常见的匹配,大大减少了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;
Run Code Online (Sandbox Code Playgroud)

处理最初在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/