终极 YouTube 正则表达式
采摘樱桃
因为解释的时间越来越长,我把最后的结果放在最上面。随意复制+粘贴,然后继续。有关详细说明,请阅读下面的_“完整故事”_。
/**
* JavaScript function to match (and return) the video Id
* of any valid Youtube Url, given as input string.
* @author: Stephan Schmitz <eyecatchup@gmail.com>
* @url: https://stackoverflow.com/a/10315969/624466
*/
function ytVidId(url) {
var p = /^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/;
return (url.match(p)) ? RegExp.$1 : false;
}
完整的故事
乍一看,Amarghosh 的正则表达式看起来不错。但它:
- 与包含破折号 (-) 的视频 ID 不匹配,
- 不验证 id 长度(
v=aa
并v=aaaaaaaaaaaaaaaaaa
返回有效),
- 并且根本不匹配受保护的 URL (http s ://youtube.com/watch?valid_params)
为了匹配 https、破折号字符并验证 id 长度,这是我对 Amarghosh 正则表达式的修改版本的初步建议:
^https?:\/\/(?:www\.)?youtube\.com\/watch\?(?=.*v=((\w|-){11}))(?:\S+)?$
更新 1:URL 与字符串
在我贴出上述模式后,有人问我:“如果URL是这样的
youtube.com/watch?gl=US&hl=en-US&v=bQVoAWSP7k4
怎么办;”?
首先,请注意这根本不是URL。符合 RFC 的 URL必须以方案开头!;)
无论如何,为了匹配任何类型的表示引用 YouTube 视频的字符串,我更新了我的答案以排除所需的 URL 方案。所以我的第二个建议如下:
^(?:https?:\/\/)?(?:www\.)?youtube\.com\/watch\?(?=.*v=((\w|-){11}))(?:\S+)?$
更新 2:终极正则表达式
然后我被要求添加对“特殊情况”的支持;在youtu.be短网址。最初我没有添加这些,因为它不是问题的具体部分。但是,我现在用所有可能的“特殊情况”更新了我的答案。这意味着我不仅添加了对 youtu.be 链接的支持,还添加了请求路径“/v”和“/embed”。
那么,我可以介绍一下:我的最终和最终的 Youtube 正则表达式:
^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$
匹配哪些字符串?
现在这个模式适用于任何字符串,格式如下:
没有方案和子域(域:youtu.be,路径:/)
youtu.be/<video:id>
没有方案,有子域(域:youtu.be,路径:/)
www.youtu.be/<video:id>
带HTTP方案,不带子域(域:youtu.be,路径:/)
http://youtu.be/<video:id>
使用 HTTP 方案和子域(域:youtu.be,路径:/)
http://www.youtu.be/<video:id>
使用 HTTPS 方案,无子域(域:youtu.be,路径:/)
https://youtu.be/<video:id>
使用 HTTPS 方案和子域(域:youtu.be,路径:/)
https://www.youtu.be/<video:id>
没有方案和子域(域:youtube.com,路径:/embed)
youtube.com/embed/<video:id>
youtube.com/embed/<video:id>&other_params
没有方案,有子域(域:youtube.com,路径:/embed)
www.youtube.com/embed/<video:id>
www.youtube.com/embed/<video:id>&other_params
使用 HTTP 方案,没有子域(域:youtube.com,路径:/embed)
http://youtube.com/embed/<video:id>
http://youtube.com/embed/<video:id>&other_params
使用 HTTP 方案和子域(域:youtube.com,路径:/embed)
http://www.youtube.com/embed/<video:id>
http://www.youtube.com/embed/<video:id>&other_params
使用 HTTPS 方案,没有子域(域:youtube.com,路径:/embed)
https://youtube.com/embed/<video:id>
https://youtube.com/embed/<video:id>&other_params
使用 HTTPS 方案和子域(域:youtube.com,路径:/embed)
https://www.youtube.com/embed/<video:id>
https://www.youtube.com/embed/<video:id>&other_params
没有方案和子域(域:youtube.com,路径:/v)
youtube.com/v/<video:id>
youtube.com/v/<video:id>&other_params
没有方案,有子域(域:youtube.com,路径:/v)
www.youtube.com/v/<video:id>
www.youtube.com/v/<video:id>&other_params
使用 HTTP 方案,没有子域(域:youtube.com,路径:/v)
http://youtube.com/v/<video:id>
http://youtube.com/v/<video:id>&other_params
使用 HTTP 方案和子域(域:youtube.com,路径:/v)
http://www.youtube.com/v/<video:id>
http://www.youtube.com/v/<video:id>&other_params
使用 HTTPS 方案,没有子域(域:youtube.com,路径:/v)
https://youtube.com/v/<video:id>
https://youtube.com/v/<video:id>&other_params
使用 HTTPS 方案和子域(域:youtube.com,路径:/v)
https://www.youtube.com/v/<video:id>
https://www.youtube.com/v/<video:id>&other_params
没有方案和子域(域:youtube.com,路径:/watch)
youtube.com/watch?v=<video:id>
youtube.com/watch?v=<video:id>&other_params
youtube.com/watch?other_params&v=<video:id>
youtube.com/watch?other_params&v=<video:id>&more_params
没有方案,有子域(域:youtube.com,路径:/watch)
www.youtube.com/watch?v=<video:id>
www.youtube.com/watch?v=<video:id>&other_params
www.youtube.com/watch?other_params&v=<video:id>
www.youtube.com/watch?other_params&v=<video:id>&more_params
使用 HTTP 方案,没有子域(域:youtube.com,路径:/watch)
http://youtube.com/watch?v=<video:id>
http://youtube.com/watch?v=<video:id>&other_params
http://youtube.com/watch?other_params&v=<video:id>
http://youtube.com/watch?other_params&v=<video:id>&more_params
使用 HTTP 方案和子域(域:youtube.com,路径:/watch)
http://www.youtube.com/watch?v=<video:id>
http://www.youtube.com/watch?v=<video:id>&other_params
http://www.youtube.com/watch?other_params&v=<video:id>
http://www.youtube.com/watch?other_params&v=<video:id>&more_params
使用 HTTPS 方案,没有子域(域:youtube.com,路径:/watch)
https://youtube.com/watch?v=<video:id>
https://youtube.com/watch?v=<video:id>&other_params
https://youtube.com/watch?other_params&v=<video:id>
https://youtube.com/watch?other_params&v=<video:id>&more_params
使用 HTTPS 方案和子域(域:youtube.com,路径:/watch)
https://www.youtube.com/watch?v=<video:id>
https://www.youtube.com/watch?v=<video:id>&other_params
https://www.youtube.com/watch?other_params&v=<video:id>
https://www.youtube.com/watch?other_params&v=<video:id>&more_params
功能用途
使用该模式的最简单方法是将其包装成一个函数,例如:
/**
* JavaScript function to match (and return) the video Id
* of any valid Youtube Url, given as input string.
* @author: Stephan Schmitz <eyecatchup@gmail.com>
* @url: https://stackoverflow.com/a/10315969/624466
*/
function ytVidId(url) {
var p = /^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/;
return (url.match(p)) ? RegExp.$1 : false;
}
// for example snippet only!
document.body.addEventListener('click', function(e) {
if (e.target.className == 'yt-url' && 'undefined' !== e.target.value) {
var ytId = ytVidId(e.target.value);
alert(e.target.value + "\r\nResult: " + (!ytId ? 'false' : ytId));
}
}, false);
<!-- Click the buttons to probe URLs -->
<input type="button" value="https://www.youtube.com/watch?v=p-e2G_VcTms&feature=g-logo&context=G29aead6FOAAAAAAABAA" class="yt-url">
<input type="button" value="https://www.youtube.com/latest" class="yt-url">
如果函数结果值的类型必须是布尔值,只需替换RegExp.$1
为true
。而已。
关于视频 ID 长度的最后一个说明:有人问 id 是否具有 11 个字符的固定长度?如果将来可能会改变?
这个问题的最佳答案可能也是我在这里找到的唯一“官方”声明,它说:“我在文档中没有看到我们正式Promise YouTube 视频 ID 的标准长度为 11 个字符的任何地方. 这是我们当前实施的其中一件事,它可能会无限期地保持这种状态。但我们不会对此提供任何官方Promise,因此请自行承担风险。”