Улучшение регулярных выражений для разбора URL YouTube / Vimeo - PullRequest
16 голосов
/ 10 апреля 2011

Я создал функцию (в JavaScript), которая получает URL-адрес с YouTube или Vimeo. Он определяет поставщика и идентификатор для этого конкретного видео (демо: 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) Существуют ли URL-адреса YouTube или Vimeo, которые не будут проанализированы? Я пробовал немало, и до сих пор кажется, что он работает довольно хорошо.

Подводя итог: Я просто ищу способы улучшить вышеуказанную функцию. Любой совет с благодарностью.

Ответы [ 9 ]

21 голосов
/ 31 марта 2014

Вот моя попытка регулярного выражения, которая охватывает большинство обновленных случаев:

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
    };
}
11 голосов
/ 12 февраля 2014

Regex удивительно лаконичен, но может быстро усложниться.

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/'
  ]);
}

Что вы предпочитаете обновлять?

10 голосов
/ 10 апреля 2011

Я не уверен в вашем вопросе 3), но при условии, что ваша индукция в формах URL правильная, регулярные выражения можно объединить в одно из следующих:

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

Вы получите матч в разных позициях (1-й и 2-й матчи, если Vimeo, 3-й и 4-й матчи, если YouTube), так что вам просто нужно обработать это.

Или, если вы абсолютно уверены, что идентификатор vimeo содержит только цифры, вы можете сделать:

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

, а провайдер и идентификатор появятся в первом и втором матчах соответственно.

7 голосов
/ 10 апреля 2011

Вот мое регулярное выражение

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

6 голосов
/ 19 декабря 2011

о ответе Сайки:

небольшое обновление для второго регулярного выражения:

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

(экранирование точек предотвращает совпадение URL типа www_vimeo_com /… и $ добавлен…)

здесьта же идея для сопоставления встроенных URL:

/http:\/\/(?:www\.|player\.)?(vimeo|youtube)\.com\/(?:embed\/|video\/)?(.*?)(?:\z|$|\?)/
5 голосов
/ 02 октября 2017

Для Vimeo Не полагайтесь на Regex , поскольку Vimeo время от времени имеет тенденцию изменять / обновлять свой шаблон URL.По состоянию на 2 октября 2017 года существует всего шесть схем URL, поддерживаемых Vimeo.

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 для проверки URL-адресов vimeo.Вот этот oEmbed ( doc ) 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
  }
});
1 голос
/ 27 апреля 2016

На всякий случай вот версия 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
        );
} 
1 голос
/ 04 апреля 2014

3) Ваше регулярное выражение не соответствует URL https.Я не проверял это, но я предполагаю, что "http://" часть станет" http (s)?: // ". Обратите внимание, что это изменит соответствующие позиции поставщика и идентификатора.

0 голосов
/ 28 июня 2019

Я основывал себя на предыдущих ответах, но мне нужно было больше использовать регулярное выражение.

Возможно, это сработало в 2011 году, но в 2019 году синтаксис немного изменился. Так что это обновление.

Регулярное выражение позволит нам определить, является ли URL Youtube или Vimeo. Я добавил группу Capture, чтобы легко получить 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

...