【问题标题】:Extract URLs from text in PHP从 PHP 中的文本中提取 URL
【发布时间】:2010-10-28 23:54:19
【问题描述】:

我有这段文字:

$string = "this is my friend's website http://example.com I think it is coll";

如何将链接提取到另一个变量中?

我知道应该使用正则表达式,尤其是preg_match(),但我不知道怎么做?

【问题讨论】:

  • Extract URL from string 的可能重复项
  • @Michael Berkowski 如何复制用户在 09 年 5 月 26 日 14:13 提出的问题,但您在 2010 年 12 月 8 日 17:44 提出的链接。可能反过来也可能正确。

标签: php html regex


【解决方案1】:
preg_match_all('/[a-z]+:\/\/\S+/', $string, $matches);

这是一种简单的方法,适用于很多情况,而不是所有情况。所有匹配项都放在 $matches 中。请注意,这不包括锚元素中的链接(

【讨论】:

  • -1:您刚刚创建了一个 XSS 漏洞,因为它还会提取 javascript: URL。
  • 没有说明他会用它做什么,因此我不考虑这一点。他只是想将 URL 放入变量中。
  • @Michael:查找 javascript URL 还不是漏洞;使用它们没有任何检查是。有时,此类 URL 的存在和数量是有用的信息。我会选择不同的分隔符。 :)
【解决方案2】:

URL 有一个相当 complex definition — 您必须先决定要捕获的内容。捕获以http://https:// 开头的任何内容的简单示例可能是:

preg_match_all('!https?://\S+!', $string, $matches);
$all_urls = $matches[0];

请注意,这是非常基本的,可能会捕获无效的 URL。对于更复杂的事情,我建议您关注 POSIXPHP regular expressions

【讨论】:

    【解决方案3】:

    如果您从中提取 URL 的文本是用户提交的,并且您要将结果显示为任何地方的链接,您必须非常非常小心地避免 XSS vulnerabilities,最突出的是“javascript:”协议 URL ,还有malformed URLs 可能会欺骗您的正则表达式和/或显示浏览器将它们作为Javascript URL 执行。至少,您应该只接受以“http”、“https”或“ftp”开头的 URL。

    还有一个由 Jeff 撰写的 blog entry,他在其中描述了提取 URL 的一些其他问题。

    【讨论】:

      【解决方案4】:

      可能最安全的方法是使用来自 WordPress 的代码 sn-ps。下载最新版本(当前为 3.1.1)并查看 wp-includes/formatting.php。有一个名为 make_clickable 的函数,它具有纯文本的参数并返回格式化的字符串。您可以获取用于提取 URL 的代码。不过这很复杂。

      这一行正则表达式可能会有所帮助。

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

      但是这个正则表达式仍然无法删除一些格式错误的 URL(例如 http://google:ha.ckers.org )。

      另请参阅: How to mimic StackOverflow Auto-Link Behavior

      【讨论】:

      • 我玩过 Wordpressformatting.php,使用 make_clickable 是个好主意,但它最终会在依赖项中吸收一半的 wordpress。
      • 好的,确保终端部分不是奇怪的字符
      • 这不识别没有http的url,比如google.com
      • 这个正则表达式将匹配google:ha.ckers.org "@https?:\/\/(www\.)?[-a-zA-Z0-9\@:%._\+~#= ]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()\@:%_\+.~#?&// =]*)@";不要记得我在哪里找到它所以不能给予信任
      • stackoverflow.com/questions/23366790/… 对我来说比这更好(上下文 WordPress)。
      【解决方案5】:
      preg_match_all ("/a[\s]+[^>]*?href[\s]?=[\s\"\']+".
                      "(.*?)[\"\']+.*?>"."([^<]+|.*?)?<\/a>/",
                      $var, &$matches);
      
      $matches = $matches[1];
      $list = array();
      
      foreach($matches as $var)
      {    
          print($var."<br>");
      }
      

      【讨论】:

        【解决方案6】:

        我尝试按照 Nobu 所说的使用 Wordpress 进行操作,但是由于对其他 WordPress 函数的依赖程度很高,我选择使用 Nobu 的 preg_match_all() 正则表达式并将其转换为函数,使用 preg_replace_callback();现在用可点击的链接替换文本中的所有链接的功能。它使用anonymous functions,因此您需要 PHP 5.3,或者您可以重写代码以使用普通函数。

        <?php 
        
        /**
         * Make clickable links from URLs in text.
         */
        
        function make_clickable($text) {
            $regex = '#\bhttps?://[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/))#';
            return preg_replace_callback($regex, function ($matches) {
                return "<a href=\'{$matches[0]}\'>{$matches[0]}</a>";
            }, $text);
        }
        

        【讨论】:

        • 请注意:我已将您的答案更新为使用匿名函数作为回调,而不是使用 create_function()
        【解决方案7】:

        你可以这样做..

        <?php
        $string = "this is my friend's website http://example.com I think it is coll";
        echo explode(' ',strstr($string,'http://'))[0]; //"prints" http://example.com
        

        【讨论】:

          【解决方案8】:

          对我有用的代码(特别是如果您的 $string 中有多个链接):

          $string = "this is my friend's website https://www.example.com I think it is cool, but this one is cooler https://www.stackoverflow.com :)";
          $regex = '/\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i';
          preg_match_all($regex, $string, $matches);
          $urls = $matches[0];
          // go over all links
          foreach($urls as $url) 
          {
              echo $url.'<br />';
          }
          

          希望对其他人也有帮助。

          【讨论】:

          • 我已经测试了所有答案,这只是一个将删除 html 选项卡
          【解决方案9】:

          您可以尝试这个来找到链接并修改链接(添加 href 链接)。

          $reg_exUrl = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";
          
          // The Text you want to filter for urls
          $text = "The text you want to filter goes here. http://example.com";
          
          if(preg_match($reg_exUrl, $text, $url)) {
          
                 echo preg_replace($reg_exUrl, "<a href="{$url[0]}">{$url[0]}</a> ", $text);
          
          } else {
          
                 echo "No url in the text";
          
          }
          

          参考这里:http://php.net/manual/en/function.preg-match.php

          【讨论】:

            【解决方案10】:

            这个正则表达式非常适合我,我检查了所有类型的 URL,

            <?php
            $string = "Thisregexfindurlhttp://www.rubular.com/r/bFHobduQ3n mixedwithstring";
            preg_match_all('/(https?|ssh|ftp):\/\/[^\s"]+/', $string, $url);
            $all_url = $url[0]; // Returns Array Of all Found URL's
            $one_url = $url[0][0]; // Gives the First URL in Array of URL's
            ?>
            

            检查了很多网址可以在这里找到http://www.rubular.com/r/bFHobduQ3n

            【讨论】:

              【解决方案11】:
              public function find_links($post_content){
                  $reg_exUrl = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";
                  // Check if there is a url in the text
                  if(preg_match_all($reg_exUrl, $post_content, $urls)) {
                      // make the urls hyper links,
                      foreach($urls[0] as $url){
                          $post_content = str_replace($url, '<a href="'.$url.'" rel="nofollow"> LINK </a>', $post_content);
                      }
                      //var_dump($post_content);die(); //uncomment to see result
                      //return text with hyper links
                      return $post_content;
                  } else {
                      // if no urls in the text just return the text
                      return $post_content; 
                  }
              }
              

              【讨论】:

                【解决方案12】:

                url 有很多边缘情况。像 url 可以包含括号或不包含协议等。这就是为什么正则表达式是不够的。

                我创建了一个可以处理大量边缘情况的 PHP 库:Url highlight

                例子:

                <?php
                
                use VStelmakh\UrlHighlight\UrlHighlight;
                
                $urlHighlight = new UrlHighlight();
                $urlHighlight->getUrls("this is my friend's website http://example.com I think it is coll");
                // return: ['http://example.com']
                

                更多详情请见readme。对于覆盖的 url 案例,请参阅test

                【讨论】:

                  【解决方案13】:

                  这是我使用的一个函数,不记得它来自哪里,但似乎在文本中查找链接方面做得很好。并使它们成为链接。

                  您可以更改功能以满足您的需要。我只是想分享这个,因为我环顾四周并记得我在我的一个助手库中有这个。

                  function make_links($str){
                  
                    $pattern = '(?xi)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'".,<>?«»“”‘’]))';
                  
                    return preg_replace_callback("#$pattern#i", function($matches) {
                      $input = $matches[0];
                      $url = preg_match('!^https?://!i', $input) ? $input : "http://$input";
                      return '<a href="' . $url . '" rel="nofollow" target="_blank">' . "$input</a>";
                    }, $str);
                  } 
                  

                  用途:

                  $subject = 'this is a link http://google:ha.ckers.org maybe don't want to visit it?';
                  echo make_links($subject);
                  

                  输出

                  this is a link <a href="http://google:ha.ckers.org" rel="nofollow" target="_blank">http://google:ha.ckers.org</a> maybe don't want to visit it?
                  

                  【讨论】:

                    【解决方案14】:
                    <?php
                    preg_match_all('/(href|src)[\s]?=[\s\"\']?+(.*?)[\s\"\']+.*?/', $webpage_content, $link_extracted);
                    

                    preview

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2011-11-27
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2023-04-04
                      相关资源
                      最近更新 更多