从PHP中的文本中提取URL

时间:2009-05-26 14:13:56

标签: php html regex

我有这样的文字:

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

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

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

14 个答案:

答案 0 :(得分:45)

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

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

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

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

另见: How to mimic StackOverflow Auto-Link Behavior

答案 1 :(得分:15)

我尝试按照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);
}

答案 2 :(得分:12)

网址非常complex definition - 您必须先决定要捕获的内容。捕获以http://https://开头的任何内容的简单示例可能是:

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

请注意,这是非常基本的,可能会捕获无效的网址。我会建议赶上POSIXPHP regular expressions以获取更复杂的内容。

答案 3 :(得分:8)

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

杰夫还有一个blog entry,他描述了一些提取网址的其他问题。

答案 4 :(得分:5)

你可以这样做..

<?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

答案 5 :(得分:5)

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

$string = "this is my friend's website http://example.com I think it is cool, but this is cooler http://www.memelpower.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 />';
}

希望能帮助他人。

答案 6 :(得分:4)

preg_match_all('/[a-z]+:\/\/\S+/', $string, $matches);

这是一种适用于很多情况的简单方法,而不是全部。所有比赛都放在$ match中。请注意,这不包括锚元素中的链接(&lt; a href =“”...),但这也不在您的示例中。

答案 7 :(得分:2)

preg_match_all ("/a[\s]+[^>]*?href[\s]?=[\s\"\']+".
                "(.*?)[\"\']+.*?>"."([^<]+|.*?)?<\/a>/",
                $var, &$matches);

$matches = $matches[1];
$list = array();

foreach($matches as $var)
{    
    print($var."<br>");
}

答案 8 :(得分:2)

你可以尝试这个来找到链接并修改链接(添加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

答案 9 :(得分:1)

有很多带有网址的极端情况。像url可能包含方括号或不包含协议等。这就是为什么regex不够的原因。

我创建了一个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。有关覆盖的网址情况,请参见test

答案 10 :(得分:1)

<?php
preg_match_all('/(href|src)[\s]?=[\s\"\']?+(.*?)[\s\"\']+.*?/', $webpage_content, $link_extracted);

preview

答案 11 :(得分:0)

这个正则表达式对我很有用,我已经检查了所有类型的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

答案 12 :(得分:0)

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; 
    }
}

答案 13 :(得分:0)

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

您可以根据需要更改功能。当我环顾四周时,我只是想分享一下,并记得我在一个帮助器库中有这个。

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?