Javascript 改进用于解析YouTube/Vimeo URL的正则表达式

Javascript 改进用于解析YouTube/Vimeo URL的正则表达式,javascript,regex,youtube,vimeo,Javascript,Regex,Youtube,Vimeo,我制作了一个函数(JavaScript),它从YouTube或Vimeo获取URL。它计算出特定视频的提供者和ID(演示:) 不过,作为一名regex新手,我正在寻找改进的方法。我处理的输入通常如下所示: http://vimeo.com/(id) http://youtube.com/watch?v=(id)&blahblahblah..... 1) 现在我正在做三个独立的匹配,尝试在一个表达式中完成所有操作是否有意义?如果是,怎么做 2) 现有的匹配是否更简洁?它们是否过于复杂?或

我制作了一个函数(JavaScript),它从YouTube或Vimeo获取URL。它计算出特定视频的提供者和ID(演示:)

不过,作为一名regex新手,我正在寻找改进的方法。我处理的输入通常如下所示:

http://vimeo.com/(id)
http://youtube.com/watch?v=(id)&blahblahblah.....
1) 现在我正在做三个独立的匹配,尝试在一个表达式中完成所有操作是否有意义?如果是,怎么做

2) 现有的匹配是否更简洁?它们是否过于复杂?或者可能不够

3) 是否有任何YouTube或Vimeo URL无法解析?我已经试过很多次了,到目前为止似乎效果不错


总而言之:我只是在寻找改进上述功能的方法。非常感谢您的建议。

我不确定您的问题3),但如果您对url表单的归纳是正确的,则可以将正则表达式组合为一个,如下所示:

/http:\/\/(?:www.)?(?:(vimeo).com\/(.*)|(youtube).com\/watch\?v=(.*?)&)/
你将在不同的位置获得比赛(如果vimeo,第一场和第二场比赛,如果youtube,第三场和第四场比赛),所以你只需要处理这个问题

或者,如果您非常确定vimeo的id只包含数字,那么您可以执行以下操作:

/http:\/\/(?:www.)?(vimeo|youtube).com\/(?:watch\?v=)?(.*?)(?:\z|&)/
提供者和id将分别在第一次和第二次匹配时通知。

这是我的正则表达式


关于萨瓦的回答:

第二个正则表达式的一些更新:

/http:\/\/(?:www\.)?(vimeo|youtube)\.com\/(?:watch\?v=)?(.*?)(?:\z|$|&)/
(转义点会阻止匹配类型为www_vimeo_com/…和$added…)的url)

以下是匹配嵌入URL的相同想法:

/http:\/\/(?:www\.|player\.)?(vimeo|youtube)\.com\/(?:embed\/|video\/)?(.*?)(?:\z|$|\?)/
正则表达式非常简洁,但很快就会变得复杂。

有时候,简单的代码对您的开发伙伴来说更好。


您更喜欢更新哪一个?下面是我在正则表达式中的尝试,它涵盖了大多数更新的情况:

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(/(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
    };
}

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

以防这里是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
        );
} 

对于Vimeo,不要依赖于Regex,因为Vimeo往往会不时更改/更新其URL模式。截至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 URL。这是一个oEmbed()API,它获取一个URL,检查其有效性,并返回一个包含大量视频信息的对象(查看dev页面)。虽然不是有意的,但我们可以很容易地使用它来验证给定的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
  }
});

我基于之前的答案,但我需要更多的正则表达式

也许它在2011年起作用,但在2019年,语法发生了一些变化。这是一次刷新

正则表达式将允许我们检测url是Youtube还是Vimeo。 我添加了捕获组,以便轻松检索视频ID

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

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

我有一项任务,可以添加dropbox视频。所以相同的输入应该是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.");
        }
    }
}

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})[?]?.*$/
^^这只是两个单独表达式的组合,使用
|
(or)将它们连接起来。以下是两个单独的原始表达式:

/^(?: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工作的。希望这对将来的人有所帮助。

哦!还有小小的URL表单:
/^http:\/\/youtu\.be\/(.+?)(?:$)/
这个正则表达式不够好,它匹配
http://player.youtube.com/sdfsdfdf
这不是一个有效的youtube URL。它不适用于URL,例如。结果,我得到了
对象{provider:“youtube”,id:“My2FRPA3Gf”}
。请注意id中缺少的8。有关完整的YouTube解析器,请参阅stackoverflow.com/a/5831191/208457。对于vimeo.com之类的内容,这只是一个小小的改进:(http:\/\/\\;https:\/\/\\)/12143242@flp谢谢你的建议,我已经把它合并了。你能告诉我这个url是在哪个方案下建立的吗:
https://vimeo.com/334343427/4332adfeb6
fall?
(?:(?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]+))
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.");
        }
    }
}
/^(?: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})[?]?.*$/
/^(?: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})[?]?.*$/