Como encontro todos os IDs de vídeo do YouTube em uma string usando um regex?

91

Eu tenho um campo de texto onde os usuários podem escrever qualquer coisa.

Por exemplo:

Lorem Ipsum é simplesmente um texto fictício. http://www.youtube.com/watch?v=DUQi_R4SgWo da indústria de impressão e composição. Lorem Ipsum tem sido o texto fictício padrão da indústria desde 1500, quando um impressor desconhecido pegou um modelo de impressão e o embaralhou para fazer um livro de amostra de tipos. Ele sobreviveu não apenas cinco séculos, mas também ao salto para a composição eletrônica, permanecendo essencialmente inalterado. http://www.youtube.com/watch?v=A_6gNZCkajU&feature=relmfu Foi popularizado na década de 1960 com o lançamento de folhas de Letraset contendo passagens de Lorem Ipsum e, mais recentemente, com software de editoração eletrônica como Aldus PageMaker incluindo versões de Lorem Ipsum.

Agora eu gostaria de analisá-lo e encontrar todos os URLs de vídeo do YouTube e seus ids.

Alguma ideia de como isso funciona?

n00b
fonte

Respostas:

289

Um URL de vídeo do YouTube pode ser encontrado em vários formatos:

  • formato curto mais recente: http://youtu.be/NLqAF9hrVbY
  • iframe: http://www.youtube.com/embed/NLqAF9hrVbY
  • iframe (seguro): https://www.youtube.com/embed/NLqAF9hrVbY
  • parâmetro de objeto: http://www.youtube.com/v/NLqAF9hrVbY?fs=1&hl=en_US
  • incorporação de objetos: http://www.youtube.com/v/NLqAF9hrVbY?fs=1&hl=en_US
  • ver: http://www.youtube.com/watch?v=NLqAF9hrVbY
  • Comercial: http://www.youtube.com/user/Scobleizer#p/u/1/1p3vcRhsYGo
  • ytscreeningroom: http://www.youtube.com/ytscreeningroom?v=NRHVzbJVx8I
  • qualquer coisa serve!: http://www.youtube.com/sandalsResorts#p/c/54B8C800269D7C1B/2/PPS-8DMrAn4
  • qualquer / subdomínio / também: http://gdata.youtube.com/feeds/api/videos/NLqAF9hrVbY
  • mais params: http://www.youtube.com/watch?v=spDj54kf-vY&feature=g-vrec
  • a consulta pode ter um ponto: http://www.youtube.com/watch?v=spDj54kf-vY&feature=youtu.be
  • domínio nocookie: http://www.youtube-nocookie.com

Aqui está uma função PHP com uma regex comentada que corresponde a cada um desses formulários de URL e os converte em links (se ainda não forem links):

// 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,
          [^\w\s-]         # 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;
}

; // Fim de $ YouTubeId.

E aqui está uma versão JavaScript com exatamente a mesma regex (com comentários removidos):

// Linkify youtube URLs which are not already links.
function linkifyYouTubeURLs(text) {
    var re = /https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube(?:-nocookie)?\.com\S*?[^\w\s-])([\w-]{11})(?=[^\w-]|$)(?![?=&+%\w.-]*(?:['"][^<>]*>|<\/a>))[?=&+%\w.-]*/ig;
    return text.replace(re,
        '<a href="http://www.youtube.com/watch?v=$1">YouTube link: $1</a>');
}

Notas:

  • A parte VIDEO_ID da URL é capturado no grupo único e captura: $1.
  • Se você sabe que seu texto não contém URLs pré-vinculados, pode remover com segurança a afirmação antecipada negativa que testa essa condição (a afirmação que começa com o comentário: "Afirmar que o URL não está pré-vinculado." ) Isso irá acelerar até o regex um pouco.
  • A string de substituição pode ser modificada para se adequar. O fornecido acima simplesmente cria um link para o genérico "http://www.youtube.com/watch?v=VIDEO_ID"URL estilo e define o texto link: "YouTube link: VIDEO_ID".

Editar 05-07-2011:- Hífen adicionado à classe ID char

Editar 2011-07-17: Corrigido regex para consumir qualquer parte restante (por exemplo, consulta ) de URL após o ID do YouTube. Adicionado modificador 'i' ignore-case . Função renomeada para camelCase. Teste antecipado pré-vinculado aprimorado.

Editar 27/07/2011: Novos formatos de "usuário" e "ytscreeningroom" adicionados aos URLs do YouTube.

Editar 02-08-2011: simplificado / generalizado para lidar com novos URLs "qualquer / coisa / vai" do YouTube.

Editar 25/08/2011: Várias modificações:

  • Adicionada uma versão Javascript de: linkifyYouTubeURLs()function.
  • A versão anterior tinha a parte do esquema (protocolo HTTP) opcional e, portanto, corresponderia a URLs inválidos. Tornou a parte do esquema necessária.
  • A versão anterior usava a \bpalavra âncora de limite em torno do VIDEO_ID. No entanto, isso não funcionará se o VIDEO_ID começar ou terminar com um -travessão. Corrigido para lidar com essa condição.
  • Alterada a expressão VIDEO_ID para que tenha exatamente 11 caracteres.
  • A versão anterior não conseguiu excluir URLs pré-vinculados se eles tivessem uma string de consulta seguindo o VIDEO_ID. Melhorou a afirmação de antecipação negativa para corrigir isso.
  • Adicionado +e %à classe de caracteres correspondente à string de consulta.
  • Changed versão PHP delimitador regex de: %um: ~.
  • Adicionada uma seção "Notas" com algumas notas úteis.

Editar 12/10/2011: a parte do host do URL do YouTube agora pode ter qualquer subdomínio (não apenas www.).

Editar 01-05-2012: A seção consumir URL agora pode permitir '-'.

Editar 2013-08-23: Adicionado formato adicional fornecido por @Mei. (A parte da consulta pode ter um .ponto.

Editar 2013/11/30: Adicionado formato adicional fornecida pelo @CRONUS: youtube-nocookie.com.

Editar 25/01/2016: Regex corrigido para lidar com casos de erro fornecidos pelo CRONUS.

ridgerunner
fonte
2
Eu não vi uma especificação, embora eu tenha procurado uma. Acabei de notar o traço em alguns links na selva da internet. Por exemplo: youtube.com/watch?v=CLPk-6_xgiY
cottonBallPaws
1
@littleFluffyKitty: Obrigado pelo aviso. Atualizei a resposta para incluir o hífen como um caractere de identificação válido.
ridgerunner
1
@ridgerunner: Se você não está confiante com uma edição, pode reverter. Além disso, como na wikipedia, todo o histórico é guardado com seus créditos. Eu vi você realmente acertar a resposta ao longo do tempo, então seria uma pena perdê-lo aqui.
hakre
1
Aqui está um que não funcionou: youtube.com/watch?v=E1IPnnttL9k&feature=youtu.be
andrebola
1
Isso funciona muito bem, mas falha com este (novo?) Parâmetro de querystring: feature = youtu.be. Alterar [? = & +% \ W -] * para [? = & +% \ W - \.] * Na linha "consumir url restante" resolve o problema. Obrigado!
Mei Gwilym de
10

Aqui está um método que escrevi uma vez para um projeto que extrai as chaves de vídeo do YouTube e 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\=)([\w\d-_]+)/', $vid_link, $matches))
      return array('host_name' => 'youtube', 'original_key' => $matches[0]); 
    // Ajax hash tag links
    else if (preg_match('§([\d\w-_]+)$§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;
}
  1. Encontre um regex que extrairá todos os links de um texto. O Google vai te ajudar nisso.
  2. Faça um loop em todos os links e chame getHostInfo () para cada
Christof
fonte
1
muito obrigado! A modificação leve if(strpos($vid_link, 'youtu'))irá capturar o url curto youtu.be, além do url comum.
Chamilyan,
de nada. obrigado pela atualização, eu editei na mudança. em uma nota lateral, o regex de ridgerunner parece ser o verdadeiro negócio e eu recomendo usá-lo em vez de minha coisa simples. saudações
Christof de
Exatamente o que eu estava procurando. local no companheiro! +1
blackpla9ue
8

Embora a resposta de ridgerunner seja a base para minha resposta, ele NÃO resolve para todos os urls e não acredito que seja capaz disso, devido a várias correspondências possíveis de VIDEO_IDem um URL do YouTube. Minha regex inclui sua abordagem agressiva como último recurso, mas tenta primeiro todas as correspondências comuns, reduzindo muito a possibilidade de uma correspondência errada posteriormente na URL.

Este regex:

/https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube\.com(?:\/embed\/|\/v\/|\/watch\?v=|\/ytscreeningroom\?v=|\/feeds\/api\/videos\/|\/user\S*[^\w\-\s]|\S*[^\w\-\s]))([\w\-]{11})[?=&+%\w-]*/ig;

Lida com todos os casos originalmente referenciados nos exemplos de ridgerunners, mais qualquer url que possa ter uma sequência de 11 caracteres posteriormente no url. ie:

http://www.youtube.com/watch?v=GUEZCxBcM78&feature=pyv&feature=pyv&ad=10059374899&kw=%2Bwingsuit

Aqui está um exemplo de trabalho que testa todos os URLs de amostra do YouTube:

http://jsfiddle.net/DJSwc/5/

Ezwrighter
fonte
2

Experimentar

[^\s]*youtube\.com[^\s]*?v=([-\w]+)[^\s]*

Você encontrará os IDs de vídeo no primeiro grupo de captura. O que não sei é o que é um ID de vídeo válido. No momento, eu verifico v=e capturo tudo -A-Za-z0-9_.

Eu verifiquei online aqui no rubular com sua string de amostra.

estema
fonte
2

Usar:

<?php

    // The YouTube URL string

    $youtube_url='http://www.youtube.com/watch?v=8VtUYvwktFQ';

    // Use regex to get the video ID

    $regex='#(?<=v=)[a-zA-Z0-9-]+(?=&)|(?<=[0-9]/)[^&\n]+|(?<=v=)[^&\n]+#';

    preg_match($regex, $youtube_url, $id);

    // Plug that into our HTML
?>
Noor Khan
fonte
2

Ok, fiz uma função própria. Mas acredito que seja bastante ineficiente. Quaisquer melhorias são bem-vindas:

function get_youtube_videos($string) {

    $ids = array();

    // Find all URLs
    preg_match_all('/(http|https)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/', $string, $links);

    foreach ($links[0] as $link) {
        if (preg_match('~youtube\.com~', $link)) {
            if (preg_match('/[^=]+=([^?]+)/', $link, $id)) {
                $ids[] = $id[1];
            }
        }
    }
    return $ids;
}
n00b
fonte
Se você está procurando apenas links do youtube.com, por que deseja construir primeiro uma lista com todos os links? E eu acho que não é necessário usar 3 regexes diferentes.
stema
1

Tentei uma expressão simples para obter apenas o videoid:

[?&]v=([^&#]*)

Verifique trabalhando online aqui em phpliveregex .

BL Praveen
fonte
1

O autor da postagem original perguntou "Gostaria de analisar e encontrar todos os URLs de vídeo do YouTube e seus ids." Troquei a resposta mais popular acima para preg_match e retornei o ID do vídeo e o URL.

Obtenha o URL e o ID do YouTube na postagem:

$match[0] = Full URL
$match[1] = video ID

function get_youtube_id($input) {
    $input = preg_match('~https?://(?:[0-9A-Z-]+\.)?(?:youtu\.be/|youtube(?:-nocookie)?\.com\S*[^\w\s-])([\w-]{11})(?=[^\w-]|$)(?![?=&+%\w.-]*(?:[\'"][^<>]*>|</a>))[?=&+%\w.-]*~ix',
                        $input, $match);
    return $match;
}
Lee Woodman
fonte
0

Encontre um link do YouTube facilmente em uma string:

function my_url_search($se_action_data)
{
    $regex = '/https?\:\/\/[^\" ]+/i';
    preg_match_all($regex, $se_action_data, $matches);
    $get_url=array_reverse($matches[0]);
    return array_unique($get_url);
}
echo my_url_search($se_action_data)
Mukesh Kumar Bijarniya
fonte
Isso não é apenas para YoutTube, ele irá corresponder a outros urls do conteúdo.
Rahil Wazir de
0
String urlid="" ;
String  url="http://www.youtube.com/watch?v=0zM4nApSvMg#t=0m10s";
Pattern pattern =Pattern.compile("(?:http|https|)(?::\\/\\/|)(?:www.|)(?:youtu\\.be\\/|youtube\\.com(?:\\/embed\\/|\\/v\\/|\\/watch\\?v=|\\/ytscreeningroom\\?v=|\\/feeds\\/api\\/videos\\/|\\/user\\\\S*[^\\w\\-\\s]|\\S*[^\\w\\-\\s]))([\\w\\-\\_]{11})[a-z0-9;:@#?&%=+\\/\\$_.-]*");
Matcher result = pattern.matcher(url);
    if (result.find())
    {
         urlid=result.group(1);

    }

Este código em java funciona perfeitamente bem para todos os urls do youtube no momento.

Sravya Singh
fonte