Проверка URL-адреса Youtube с помощью регулярного выражения


Я пытаюсь проверить URL-адреса YouTube для своего приложения.

Пока у меня есть следующее:

// Set the youtube URL
$youtube_url = "www.youtube.com/watch?v=vpfzjcCzdtCk";

if (preg_match("/((http\:\/\/){0,}(www\.){0,}(youtube\.com){1} || (youtu\.be){1}(\/watch\?v\=[^\s]){1})/", $youtube_url) == 1)
{
    echo "Valid";
else
{
    echo "Invalid";
}

Я хочу проверить следующие варианты URL-адресов Youtube:

  • С и без http://
  • С www и без него.
  • С URL-адресами youtube.com и youtu.be
  • Должен иметь/смотреть?v=
  • Должна иметь уникальную строку видео (в приведенном выше примере "VPFZJCCZDTCK")

Однако я не думаю, что у меня есть своя логика правильно, потому что по какой-то причине он возвращает true для: www.youtube.co/watch?v=vpfzjcCzdtCk (Обратите внимание, что я написал это неправильно с .co и не .com)

Author: Luke, 2012-11-20

5 answers

В этом вашем регулярном выражении много избыточностей (а также синдром наклоняющейся зубочистки). Это, однако, должно привести к результатам:

$rx = '~
  ^(?:https?://)?                           # Optional protocol
   (?:www[.])?                              # Optional sub-domain
   (?:youtube[.]com/watch[?]v=|youtu[.]be/) # Mandatory domain name (w/ query string in .com)
   ([^&]{11})                               # Video id of 11 characters as capture group 1
    ~x';

$has_match = preg_match($rx, $url, $matches);

// if matching succeeded, $matches[1] would contain the video ID

Некоторые примечания:

  • используйте символ тильды ~ в качестве разделителя, чтобы избежать LTS
  • используйте [.] вместо \., чтобы улучшить визуальную разборчивость и избежать LTS. ("Специальные" символы, такие как точка ., не влияют на классы символов (в квадратных скобках))
  • чтобы сделать регулярные выражения более "читабельные" вы можете использовать модификатор x (который имеет дополнительные последствия; см. документы по модификаторам шаблонов), который также позволяет добавлять комментарии в регулярные выражения
  • захват может быть подавлен с помощью групп без захвата: (?: <pattern> ). Это делает выражение более эффективным.

Необязательно, чтобы извлечь значения из (более или менее полного) URL, вы можете захотеть использовать parse_url():

$url = 'http://youtube.com/watch?v=VIDEOID';
$parts = parse_url($url);
print_r($parts);

Вывод:

Array
(
    [scheme] => http
    [host] => youtube.com
    [path] => /watch
    [query] => v=VIDEOID
)

Проверка доменного имени и извлечение идентификатора видео оставлены в качестве упражнения для читателя.


Я поддался войне комментариев ниже; благодаря Тони Ориолу регулярное выражение теперь работает на коротких (youtu.be ) также URL-адреса.

 34
Author: Linus Kleen, 2017-02-03 09:26:17

Альтернативой регулярным выражениям было бы parse_url().

 $parts = parse_url($url);
 if ($parts['host'] == 'youtube.com' && ...) {
   // your code
 }

Хотя это больше кода, он более удобочитаем и, следовательно, более удобен в обслуживании.

 5
Author: Jason McCreary, 2012-11-20 15:15:20

Пожалуйста, попробуйте:

// Set the youtube URL
$youtube_url = "www.youtube.com/watch?v=vpfzjcCzdtCk";

if (preg_match("/^((http\:\/\/){0,}(www\.){0,}(youtube\.com){1}|(youtu\.be){1}(\/watch\?v\=[^\s]){1})$/", $youtube_url) == 1)
{
    echo "Valid";
}
else
{
    echo "Invalid";
}

У вас был ||, что в любом случае нормально без ^$.

 3
Author: eisberg, 2012-11-20 15:09:25

Это должно сделать это:

$valid = preg_match("/^(https?\:\/\/)?(www\.)?(youtube\.com|youtu\.be)\/watch\?v\=\w+$/", $youtube_url);
if ($valid) {
    echo "Valid";
} else {
    echo "Invalid";
}
 3
Author: Steven Moseley, 2017-02-10 20:49:51

Я полагаюсь на другие ответы на этой странице для анализа синтаксиса URL, но для самих значений идентификатора YouTube вы можете быть немного более конкретными, как я описываю в следующем ответе на StackExchange/webapps:

Формат для идентификатора видео на YouTube - https://webapps.stackexchange.com/a/101153/141734


Идентификатор видео

Для видеоизображения это 8-байтовый (64-разрядный) целое число. Для применения кодировки Base64 к 8 байтам данных требуется 11 символов. Однако, поскольку каждый символ Base64 содержит ровно 6 бит, это распределение может фактически содержать до 11 × 6 = 66 бит - избыток в 2 бита по сравнению с тем, что требуется нашей полезной нагрузке. Избыточные биты равны нулю, что приводит к исключению появления определенных символов в последней позиции кодированной строки. В частности, Видеоид всегда будет заканчиваться одним из следующих:

{ A, E, I, M, Q, U, Y, c, g, k, o, s, w, 0, 4, 8 }

Таким образом, регулярное выражение (регулярное выражение) для видеоизображения будет выглядеть следующим образом:

[-_A-Za-z0-9]{10}[AEIMQUYcgkosw048]

Идентификатор канала или списка воспроизведения

Строки Идентификатора канала и списка воспроизведения создаются с помощью Base64-кодирования 128-битного (16-байтового) двоичного целого числа. Опять же, здесь расчет на Base64 правильно предсказывает наблюдаемую длину строки из 22 символов. В этом случае выходные данные способны кодировать 22 × 6 = 132 бит, избыток в 4 бита; эти нули заканчиваются ограничение большинства из 64 символов алфавита от появления в последней позиции, и только 4 остаются подходящими. Все строки идентификатора канала заканчиваются одним из следующих:

{ A, Q, g, w }

Это дает нам регулярное выражение для идентификатора канала :

[-_A-Za-z0-9]{21}[AQgw]
 1
Author: Glenn Slayden, 2017-04-13 12:57:16