【问题标题】:PHP: preg_match_all Youtube video IDs from textPHP:preg_match_all 来自文本的 Youtube 视频 ID
【发布时间】:2018-02-19 16:26:28
【问题描述】:

我想从文本 youtube url 字符串(如 https://www.youtube.com/watch?time_continue=218&v=0EB7zh_7UE4)和视频 ID(如 0EB7zh_7UE4)中提取,以便我可以根据视频 ID 在字符串后面注入文本。这是我的示例文本:

This is an example page will show up https://www.youtube.com/watch?time_continue=218&v=0EB7zh_7UE4 Bike https://www.youtube.com/watch?v=0EB7zh_7UE4&feature=youtu.be&app=desktop messenger by day, aspiring actor by night, and this is my website. I live in https://youtu.be/1EB7zh_7UE4 Los Angeles, have a great dog named Jack, and I https://www.youtube.com/watch?v=0EB7zh_7UE4&feature=youtu.be like piña coladasdoohickeys https://www.youtube.com/watch?v=4EB7zh_7UE4 you should go to <a href="http://example.com/wp-admin/">your dashboard</a> to delete this page and create new pages for your content. Have fun!

https://www.youtube.com/watch?v=0EB7zh_7UE4

more

https://www.youtube.com/watch?v=2EB7zh_7UE4&feature=youtu.be

That\'s all..

这是我目前得到的正则表达式,但错误如下:

  • 它在链接字符串的结尾(中间)之前添加(here) 字符串。一世 想在你的 Youtube url 链接字符串末尾添加(here)

  • 返回多个here注入

见代码:

function regex($sample_text) {
    if (preg_match_all('#(?:https?:\/\/)?(?:m\.|www\.)?(?:youtu\.be\/|youtube\-nocookie\.com\/embed\/|youtube\.com\/(?:embed\/|v\/|e\/|\?v=|shared\?ci=|watch\?v=|watch\?.+&v=))([-_A-Za-z0-9]{10}[AEIMQUYcgkosw048])(.*?)\b#s', $sample_text, $matches, PREG_SET_ORDER)) {
        print_r($matches);
        foreach ($matches as $match) {
            $add = ' (here)';
            $processed_text = str_replace($match[0], $match[0] . $add, $sample_text);
        }
    }
    return $processed_text;
}
echo regex($sample_test);

我哪里做错了?

注意:问题+示例文本已更新。

【问题讨论】:

  • “它重复 ID 值”是什么意思?预期的输出是什么,你看到的输出是什么?
  • @Syscall 这不是通用代码,而是为 stackoberflow.com 编辑的。我错过了。问题已解决。
  • $processed_text 每次都从 $sample_text 重置,而不是每个值的运行替换。
  • @IMSoP 我想在你的 Youtube url 链接字符串的末尾注入 `(here)`,而不是在中间添加它。
  • @EvilGeniusJamie 是的!那是错误的一部分。这就是我返回多重注射的原因。如此明亮!谢谢。

标签: php regex preg-match preg-match-all


【解决方案1】:

为了扩展我的评论,您每次都将结果文本替换为原始字符串 $sample_text。这是一个简单的修复,只需在开始时初始化 $processed_text,然后进行处理。

function regex($sample_text) {
    $processed_text = $sample_text;
    if (preg_match_all('#(?:https?:\/\/)?(?:m\.|www\.)?(?:youtu\.be\/|youtube\-nocookie\.com\/embed\/|youtube\.com\/(?:embed\/|v\/|e\/|\?v=|shared\?ci=|watch\?v=|watch\?.+&v=))([-_A-Za-z0-9]{10}[AEIMQUYcgkosw048])(.*?)\b#s', $sample_text, $matches, PREG_SET_ORDER)) {
        print_r($matches);
        foreach ($matches as $match) {
            $add = ' (here)';
            $processed_text = str_replace($match[0], $match[0] . $add, $processed_text);
        }
    }
    return $processed_text;
}
echo regex($sample_test);

您的正则表达式也不匹配 URL 的末尾。出于您提供的示例文本的目的,您可以匹配任何不是空格的内容:

'#(?:https?:\/\/)?(?:m\.|www\.)?(?:youtu\.be\/|youtube\-nocookie\.com\/embed\/|youtube\.com\/(?:embed\/|v\/|e\/|\?v=|shared\?ci=|watch\?v=|watch\?.+&v=))([-_A-Za-z0-9]{10}[AEIMQUYcgkosw048])\S*#s'

但是,这与 ". 等字符不匹配,但您可以将它们作为 | 添加到组中。您似乎对正则表达式有很好的掌握,所以我假设您可以解决这个问题 - 如果没有,请发表评论,我会更新我的答案。


为了完整起见,我在我的正则表达式中包含了完整的代码:

function regex($sample_text) {
    $processed_text = $sample_text;
    if (preg_match_all('#(?:https?:\/\/)?(?:m\.|www\.)?(?:youtu\.be\/|youtube\-nocookie\.com\/embed\/|youtube\.com\/(?:embed\/|v\/|e\/|\?v=|shared\?ci=|watch\?v=|watch\?.+&v=))([-_A-Za-z0-9]{10}[AEIMQUYcgkosw048])\S*#s', $sample_text, $matches, PREG_SET_ORDER)) {
        print_r($matches);
        foreach ($matches as $match) {
            $add = ' (here)';
            $processed_text = str_replace($match[0], $match[0] . $add, $processed_text);
        }
    }
    return $processed_text;
}
echo regex($sample_test);

【讨论】:

  • 对不起,我不会再编辑问题了 :-) 对我来说主要问题是正则表达式。您的建议仍然不匹配所有字符串,尤其是当字符串以换行符结尾时
  • 抱歉,我错过了正则表达式中的 *。编辑了我的答案 - 这确实与您提供的 s 开关匹配到行尾(仅匹配单行)
  • 使用我提供的代码修复$processed_text 问题,然后用我提供的正则表达式替换该代码中的正则表达式。
  • 我之所以选择这个答案,是因为我最符合我的初衷。谢谢大家!
【解决方案2】:
<?php

$str = 'This is an example page will show up https://www.youtube.com/watch?time_continue=218&v=0EB7zh_7UE4 Bike https://www.youtube.com/watch?v=1EB7zh_7UE4&feature=youtu.be&app=desktop messenger by day, aspiring actor by night, and this is my website. I live in https://youtu.be/2EB7zh_7UE4 Los Angeles, have a great dog named Jack, and I https://www.youtube.com/watch?v=3EB7zh_7UE4&feature=youtu.be like piña coladasdoohickeys https://www.youtube.com/watch?v=4EB7zh_7UE4 you should go to <a href="http://example.com/wp-admin/">your dashboard</a> to delete this page and create new pages for your content. Have fun!

https://www.youtube.com/watch?v=5EB7zh_7UE4

more

https://www.youtube.com/watch?v=6EB7zh_7UE4&feature=youtu.be

That\'s all.';

preg_match_all('#\bhttps?://[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/))#', $str, $match);

// youtube vid ID array placeholder
$youtubeVids = array();

// Going through each URL and retrieving the video ID
foreach($match[0] as $url)
{
    // Parsing the URL
    $url = parse_url($url);

    // Retrieving the query if they exist
    if(isset($url['query']))
    {
        parse_str($url['query'], $yt_vid);
    }

    // Checking if we have the query parts
    if(isset($yt_vid['v']))
    {
        // Adding the vid ID to the vid ID list
        $youtubeVids[] = $yt_vid['v'];
    }
    else
    {
        // No queries, checking if we are checking a youtube vid (maybe regex better?)
        if(stripos($url['host'], 'youtu') !== false)
        {
            // Adding the ID to ID list (This is mainly for links like youtube.com/6EB7zh_7UE4 or youtu.be/6EB7zh_7UE4)
            $youtubeVids[] = substr($url['path'], 1);
        }
    }

    // Unsetting so it won't be set in the next loop
    unset($yt_vid);
}

print_r($youtubeVids);
?>

输出

Array
(
    [0] => 0EB7zh_7UE4
    [1] => 1EB7zh_7UE4
    [2] => 2EB7zh_7UE4
    [3] => 3EB7zh_7UE4
    [4] => 4EB7zh_7UE4
    [5] => 5EB7zh_7UE4
    [6] => 6EB7zh_7UE4
)

我在网上找到了以下解决方案。

preg_match_all('/(?:youtube(?:-nocookie)?\.com\/(?:[^\/\n\s]+\/\S+\/|(?:v|e(?:mbed)?)\/|\S*?[?&]v=)|youtu\.be\/)([a-zA-Z0-9_-]{11})\W/', $str, $match);
print_r($match);

【讨论】:

  • 你做的很脏,但它有效!如果有人发布更好的解决方案,将保持问题开放一段时间,但你现在是最好的。
【解决方案3】:

你可以使用

https?://\S+?\Qyoutube.com\E\S+?v=\K[^&\s]+

a demo on regex101.com

【讨论】:

    【解决方案4】:

    为了记录,我最终得到了这个基于this的“简单”函数:

    function filter($content) {
    return preg_replace_callback('#(?:https?:\/\/)?(?:m\.|www\.)?(?:youtu\.be\/|youtube\-nocookie\.com\/embed\/|youtube\.com\/(?:embed\/|v\/|e\/|\?v=|shared\?ci=|watch\?v=|watch\?.+&v=))([-_A-Za-z0-9]{10}[AEIMQUYcgkosw048])\S*#s', function($match) {
        return sprintf('%s my replace with 2nd parameter found %s', $match[0], $match[1]);
    }, $content);    
    }
    

    【讨论】:

      【解决方案5】:

      这对我来说一直有效:

      function FindYouTubeId($url)
      {
      preg_match('%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu\.be/)([^"&?/ ]{11})%i', $url, $match);
      $youtube_id = $match[1];
      return $youtube_id;
      }
      

      【讨论】:

        猜你喜欢
        • 2017-05-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-15
        • 2013-09-12
        • 1970-01-01
        • 2017-06-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多