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

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

例如:

Lorem Ipsum简直就是虚拟文本。 http://www.youtube.com/watch?v=DUQi_R4SgWo印刷和排版行业。 Lorem Ipsum自从16世纪以来一直是业界标准的虚拟文本,当时一台未知的打印机采用了一种类型的厨房,并将其制作成样本书。 它不仅存活了五个世纪,而且还实现了电子排版的飞跃,基本保持不变。 http://www.youtube.com/watch?v=A_6gNZCkajU&feature=relmfu它在20世纪60年代随着包含Lorem Ipsum段落的Letraset表单的发布以及最近使用桌面出版软件(如Aldus PageMaker,包括Lorem Ipsum版本)而得到推广。

现在我想解析它并查找所有YouTube视频网址和它们的ID。

任何想法如何工作?


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

  • 最新的短格式:http: http://youtu.be/NLqAF9hrVbY
  • iframe: http://www.youtube.com/embed/NLqAF9hrVbYhttp://www.youtube.com/embed/NLqAF9hrVbY
  • iframe(安全): https://www.youtube.com/embed/NLqAF9hrVbYhttps://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 fs=1& http://www.youtube.com/v/NLqAF9hrVbY?fs=1&hl=en_US zh_CN
  • 嵌入对象: http://www.youtube.com/v/NLqAF9hrVbY?fs=1&hl=en_US : http://www.youtube.com/v/NLqAF9hrVbY?fs=1&hl=en_US fs=1& http://www.youtube.com/v/NLqAF9hrVbY?fs=1&hl=en_US
  • 请观看: http://www.youtube.com/watch?v=NLqAF9hrVbYhttp://www.youtube.com/watch?v=NLqAF9hrVbY
  • 用户: http://www.youtube.com/user/Scobleizer#p/u/1/1p3vcRhsYGohttp://www.youtube.com/user/Scobleizer#p/u/1/1p3vcRhsYGo
  • ytscreeningroom: http://www.youtube.com/ytscreeningroom?v=NRHVzbJVx8Ihttp://www.youtube.com/ytscreeningroom?v=NRHVzbJVx8I v http://www.youtube.com/ytscreeningroom?v=NRHVzbJVx8I NRHVzbJVx8I
  • 任何/东西/去!: http://www.youtube.com/sandalsResorts#p/c/54B8C800269D7C1B/2/PPS-8DMrAn4 : http://www.youtube.com/sandalsResorts#p/c/54B8C800269D7C1B/2/PPS-8DMrAn4
  • 任何/子域名/太: http://gdata.youtube.com/feeds/api/videos/NLqAF9hrVbY : 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=g-vrec spDj54kf-vY&feature http://www.youtube.com/watch?v=spDj54kf-vY&feature=g-vrec g-vrec
  • 查询可能有点: http://www.youtube.com/watch?v=spDj54kf-vY&feature=youtu.be : http://www.youtube.com/watch?v=spDj54kf-vY&feature=youtu.be spDj54kf-vY&feature= http://www.youtube.com/watch?v=spDj54kf-vY&feature=youtu.be
  • nocookie域名: http://www.youtube-nocookie.comhttp://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,
              [^ws-]         # 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版本(删除了注释):

    // Linkify youtube URLs which are not already links.
    function linkifyYouTubeURLs(text) {
        var re = /https?://(?:[0-9A-Z-]+.)?(?:youtu.be/|youtube(?:-nocookie)?.comS*?[^ws-])([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,则可以安全地删除针对此条件进行测试的否定性预测声明(声明以评论开头:“Assert URL未预先链接”)。有点正则表达式。
  • 替换字符串可以修改以适应。 上面提供的只是创建链接到通用"http://www.youtube.com/watch?v=VIDEO_ID"样式网址,并将链接文本设置为: "YouTube link: VIDEO_ID"

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

    编辑2011-07-17:修正了正则表达式消耗YouTube ID之后的URL的任何剩余部分(例如查询)。 添加了'i'忽略大小写修饰符。 将函数重命名为camelCase。 改进的预先链接的前瞻性测试。

    编辑2011-07-27:增加了新的“用户”和“ytscreeningroom”格式的YouTube网址。

    编辑2011-08-02:简化/泛化处理新的“任何/事物/去”YouTube网址。

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

  • 增加了Javascript版本: linkifyYouTubeURLs()函数。
  • 先前版本的方案(HTTP协议)部分是可选的,因此会匹配无效的URL。 制定了计划的一部分。
  • 以前的版本在VIDEO_ID周围使用b字边界锚。 但是,如果VIDEO_ID以-破折号开始或结束,则这不起作用。 固定,以便它处理这种情况。
  • 更改了VIDEO_ID表达式,使其必须正好为11个字符。
  • 如果之前的版本在VIDEO_ID后面有查询字符串,则无法排除预先链接的网址。 改进负面视图断言来解决这个问题。
  • 在字符类匹配查询字符串中添加了+%
  • 将PHP版本的正则表达式分隔符从: %更改为a: ~
  • 添加了一些便笺的“注释”部分。
  • 编辑2011-10-12: YouTube URL主机部分现在可能有任何子域名(不仅仅是www. )。

    编辑2012-05-01:消耗URL部分现在可以允许' - '。

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

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

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


    这是我曾经为提取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=)([wd-_]+)/', $vid_link, $matches))
          return array('host_name' => 'youtube', 'original_key' => $matches[0]); 
        // Ajax hash tag links
        else if (preg_match('§([dw-_]+)$§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;
    }
    
  • 找到一个将从文本中提取所有链接的正则表达式。 谷歌会帮助你。
  • 循环所有链接并为每个链接调用getHostInfo()

  • 尽管ridgerunner的回答是我回答的基础,但由于YouTube网址中有多个可能的VIDEO_ID匹配项,所以他不能解决所有网址问题,我也不相信这是有能力的。 我的正则表达式包括他作为最后手段的侵略性方法,但首先尝试所有常见匹配,这大大减少了URL后面错误匹配的可能性。

    这个正则表达式:

    /https?://(?:[0-9A-Z-]+.)?(?:youtu.be/|youtube.com(?:/embed/|/v/|/watch?v=|/ytscreeningroom?v=|/feeds/api/videos/|/userS*[^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/

    链接地址: http://www.djcxy.com/p/28921.html

    上一篇: How do I find all YouTube video ids in a string using a regex?

    下一篇: Extract parameter value from url using regular expressions