改进正则表达式以解析YouTube / Vimeo URL

时间:2011-04-10 15:01:20

标签: javascript regex youtube vimeo

我已经创建了一个从JavaScript或Vimeo获取URL的函数(在JavaScript中)。它计算出该特定视频的提供者和ID(演示:http://jsfiddle.net/csjwf/)。

function parseVideoURL(url) {

    var provider = url.match(/http:\/\/(:?www.)?(\w*)/)[2],
        id;

    if(provider == "youtube") {

        id = url.match(/http:\/\/(?:www.)?(\w*).com\/.*v=(\w*)/)[2];
    } else if (provider == "vimeo") {

        id = url.match(/http:\/\/(?:www.)?(\w*).com\/(\d*)/)[2];
    } else {
        throw new Error("parseVideoURL() takes a YouTube or Vimeo URL");    
    }
    return {
        provider : provider,
        id : id
    }
}

它有效,但作为正则表达式新手,我正在寻找改善它的方法。我正在处理的输入通常如下所示:

http://vimeo.com/(id)
http://youtube.com/watch?v=(id)&blahblahblah.....

1)现在我正在做三个单独的比赛,尝试在一个单独的表达中做所有事情是否有意义?如果是这样,怎么样?

2)现有的比赛能否更简洁?它们是不必要的复杂吗?或者可能不够?

3)是否有任何无法解析的YouTube或Vimeo网址?我已经尝试了很多,到目前为止似乎工作得很好。

总结一下:我只是在寻找改善上述功能的方法。非常感谢任何建议。

11 个答案:

答案 0 :(得分:20)

这是我对正则表达式的尝试,它涵盖了大多数更新的案例:

function parseVideo(url) {
    // - Supported YouTube URL formats:
    //   - http://www.youtube.com/watch?v=My2FRPA3Gf8
    //   - http://youtu.be/My2FRPA3Gf8
    //   - https://youtube.googleapis.com/v/My2FRPA3Gf8
    // - Supported Vimeo URL formats:
    //   - http://vimeo.com/25451551
    //   - http://player.vimeo.com/video/25451551
    // - Also supports relative URLs:
    //   - //player.vimeo.com/video/25451551

    url.match(/(http:\/\/|https:\/\/|)(player.|www.)?(vimeo\.com|youtu(be\.com|\.be|be\.googleapis\.com))\/(video\/|embed\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?/);
    var type = null;
    if (RegExp.$3.indexOf('youtu') > -1) {
        type = 'youtube';
    } else if (RegExp.$3.indexOf('vimeo') > -1) {
        type = 'vimeo';
    }

    return {
        type: type,
        id: RegExp.$6
    };
}

答案 1 :(得分:11)

正则表达式非常简洁,但很快就会变得复杂。

http://jsfiddle.net/8nagx2sk/

function parseYouTube(str) {
    // link : //youtube.com/watch?v=Bo_deCOd1HU
    // share : //youtu.be/Bo_deCOd1HU
    // embed : //youtube.com/embed/Bo_deCOd1HU

    var re = /\/\/(?:www\.)?youtu(?:\.be|be\.com)\/(?:watch\?v=|embed\/)?([a-z0-9_\-]+)/i; 
    var matches = re.exec(str);
    return matches && matches[1];
}

function parseVimeo(str) {
    // embed & link: http://vimeo.com/86164897

    var re = /\/\/(?:www\.)?vimeo.com\/([0-9a-z\-_]+)/i;
    var matches = re.exec(str);
    return matches && matches[1];
}

有时,简单的代码对您的开发人员来说更好。

https://jsfiddle.net/1dzb5ag1/

// protocol and www neutral
function getVideoId(url, prefixes) {
  var cleaned = url.replace(/^(https?:)?\/\/(www\.)?/, '');
  for(var i = 0; i < prefixes.length; i++) {
    if (cleaned.indexOf(prefixes[i]) === 0)
      return cleaned.substr(prefixes[i].length)
  }
  return undefined;
}

function getYouTubeId(url) {
  return getVideoId(url, [
    'youtube.com/watch?v=',
    'youtu.be/',
    'youtube.com/embed/',
    'youtube.googleapis.com/v/'
  ]);
}

function getVimeoId(url) {
  return getVideoId(url, [
    'vimeo.com/',
    'player.vimeo.com/'
  ]);
}

您希望更新哪个?

答案 2 :(得分:10)

我不确定您的问题3),但如果您对网址表单的归纳是正确的,那么正则表达式可以合并为一个如下:

/http:\/\/(?:www.)?(?:(vimeo).com\/(.*)|(youtube).com\/watch\?v=(.*?)&)/

你将在不同的位置得到比赛(如果你是vimeo,第3和第4场比赛,如果是youtube,那么你只需要处理它。)

或者,如果您确定vimeo的id只包含数字,那么您可以这样做:

/http:\/\/(?:www.)?(vimeo|youtube).com\/(?:watch\?v=)?(.*?)(?:\z|&)/

并且提供者和id将在第一和第二场比赛中显得非常有用。

答案 3 :(得分:7)

这是我的正则表达式

http://jsfiddle.net/csjwf/1/

答案 4 :(得分:6)

关于sawa的回答:

关于第二个正则表达式的一点点更新:

/http:\/\/(?:www\.)?(vimeo|youtube)\.com\/(?:watch\?v=)?(.*?)(?:\z|$|&)/

(逃避点数阻止匹配www_vimeo_com / ...类型的网址和$添加...)

这与匹配嵌入网址的想法相同:

/http:\/\/(?:www\.|player\.)?(vimeo|youtube)\.com\/(?:embed\/|video\/)?(.*?)(?:\z|$|\?)/

答案 5 :(得分:5)

对于Vimeo,不要依赖正则表达式,因为Vimeo会不时地更改/更新其网址格式。自 2017年10月2日以来,Vimeo共支持六种URL方案。

https://vimeo.com/*
https://vimeo.com/*/*/video/*
https://vimeo.com/album/*/video/*
https://vimeo.com/channels/*/*
https://vimeo.com/groups/*/videos/*
https://vimeo.com/ondemand/*/*

相反,请使用其API验证vimeo网址。这是一个oEmbed(doc)API,它接受一个URL,检查其有效性并返回一组包含视频信息的对象(查看开发页面)。虽然不是故意的,但我们可以轻松地使用它来验证给定的URL是否来自Vimeo。

所以,使用ajax,它看起来像这样,

var VIMEO_BASE_URL = "https://vimeo.com/api/oembed.json?url=";
var yourTestUrl = "https://vimeo.com/23374724";


$.ajax({
  url: VIMEO_BASE_URL + yourTestUrl,
  type: 'GET',
  success: function(data) {
    if (data != null && data.video_id > 0)
      // Valid Vimeo url
    else
      // not a valid Vimeo url
  },
  error: function(data) {
    // not a valid Vimeo url
  }
});

答案 6 :(得分:1)

3)你的正则表达式与https url不匹配。我没有测试过,但我想“http://”部分会变成“http(s)?://”。请注意,这会改变提供者和id的匹配位置。

答案 7 :(得分:1)

以防万一这是一个php版本

/*
* parseVideo
* @param (string) $url 
* mi-ca.ch 27.05.2016
* parse vimeo & youtube id
* format url for iframe embed 
* https://regex101.com/r/lA0fP4/1
*/

function parseVideo($url) {
  $re = "/(http:|https:|)\\/\\/(player.|www.)?(vimeo\\.com|youtu(be\\.com|\\.be|be\\.googleapis\\.com))\\/(video\\/|embed\\/|watch\\?v=|v\\/)?([A-Za-z0-9._%-]*)(\\&\\S+)?/"; 
preg_match($re, $url, $matches);

if(strrpos($matches[3],'youtu')>-1){
    $type='youtube';
    $src='https://www.youtube.com/embed/'.$matches[6];
}else if(strrpos($matches[3],'vimeo')>-1){
    $type="vimeo";
    $src='https://player.vimeo.com/video/'.$matches[6];
}else{
    return false;
}


return array(
         'type' =>  $type // return youtube or vimeo
        ,'id'   =>  $matches[6] // return the video id
        ,'src'  =>  $src // return the src for iframe embed
        );
} 

答案 8 :(得分:0)

我以以前的答案为基础,但我需要更多的正则表达式。

也许它在2011年有效,但在2019年,语法有所变化。所以这是刷新。

正则表达式将使我们能够检测到URL是Youtube或Vimeo的天气。 我添加了“捕获”组以轻松检索videoID。

如果使用不区分大小写的设置运行,请删除(?i)。

(?:(?i)(?:https:|http:)?\/\/)?(?:(?i)(?:www\.youtube\.com\/(?:embed\/|watch\?v=)|youtu\.be\/|youtube\.googleapis\.com\/v\/)(?<YoutubeID>[a-z0-9-_]{11,12})|(?:vimeo\.com\/|player\.vimeo\.com\/video\/)(?<VimeoID>[0-9]+))

https://regex101.com/r/PVdjg0/2

答案 9 :(得分:0)

我有一个任务来启用添加保管箱视频。因此,相同的输入应采用href,对其进行检查并转换为可播放的链接,然后将其插入。

const getPlayableUrl = (url) => {
    // Check youtube and vimeo
    let firstCheck = url.match(/(http:|https:|)\/\/(player.|www.)?(vimeo\.com|youtu(be\.com|\.be|be\.googleapis\.com))\/(video\/|embed\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?/);

    if (firstCheck) {
        if (RegExp.$3.indexOf('youtu') > -1) {
            return "//www.youtube.com/embed/" + RegExp.$6;
        } else if (RegExp.$3.indexOf('vimeo') > -1) {
            return 'https://player.vimeo.com/video/' + RegExp.$6
        }
    } else {
        // Check dropbox
        let candidate = ''
        if (url.indexOf('.mp4') !== -1) {
            candidate = url.slice(0, url.indexOf('.mp4') + 4)
        } else if (url.indexOf('.m4v') !== -1) {
            candidate = url.slice(0, url.indexOf('.m4v') + 4)
        } else if (url.indexOf('.webm') !== -1) {
            candidate = url.slice(0, url.indexOf('.webm') + 5)
        }

        let secondCheck = candidate.match(/(http:|https:|)\/\/(player.|www.)?(dropbox\.com)\/(s\/|embed\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*\/)?(.*)/);
        if (secondCheck) {
            return 'https://dropbox.com/' + RegExp.$4 + RegExp.$5 + RegExp.$6 + '?raw=1'
        } else {
            throw Error("Not supported video resource.");
        }
    }
}

答案 10 :(得分:0)

FWIW,我只是使用以下内容来验证和解析应用程序中的YouTube和Vimeo URL。我确定您可以添加括号以解析出您要查找的特定内容...

/^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$|^(https?:\/\/)?(www.)?(player.)?vimeo.com\/([a-z]*\/)*([0-9]{6,11})[?]?.*$/

^^这只是使用|(或)将它们连接在一起的两个单独表达式的组合。这里分别是原始的2个表达式:

/^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/

/^(https?:\/\/)?(www.)?(player.)?vimeo.com\/([a-z]*\/)*([0-9]{6,11})[?]?.*$/

我不是专家,但是按照Rubular的说法,它似乎可以正常工作。希望这可以帮助将来的某个人。