从 PHP 中的文本中提取 URL

Posted

技术标签:

【中文标题】从 PHP 中的文本中提取 URL【英文标题】:Extract URLs from text in PHP 【发布时间】: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 提出的链接。可能反过来也可能正确。 【参考方案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。对于更复杂的事情,我建议您关注 POSIX 和 php 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 *** 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()\@:%_\+.~#?&// =]*)@";不要记得我在哪里找到它所以不能给予信任 ***.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.***.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\d0,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

【讨论】:

以上是关于从 PHP 中的文本中提取 URL的主要内容,如果未能解决你的问题,请参考以下文章

php 从PHP中的URL中提取YouTube视频ID

php 从PHP中的URL中提取YouTube视频ID

php 从PHP中的URL中提取YouTube视频ID

在 MySQL 中,如何从长文本字符串中提取 URL?

如何从文本 (NVARCHAR(MAX)) 列中提取一个或多个 URL

提取并显示从 PHP 中的文本文件中分隔的所有 10 位数字逗号