可点击链接的最佳PHP脚本

时间:2012-07-26 15:50:38

标签: php url

我发现很多PHP脚本可以将文本中的网址转换为可点击的链接。但是他们中的大多数都不起作用,有些人犯了很大的错误。其中一些转换已经可点击的链接。其他人不工作,第三个从文本链接制作部分。 我需要一个只检测链接的脚本,而不是文本,并且不会转换已经可点击的链接,因为它会非常难看

我发现这个代码似乎是我测试过的最好的代码。但它有一些错误。 此代码转换可点击链接。像这样:

原件:

<a href="http://www.netload.in/dateiySgPP2b14W/1409423417ExpFut.pdf.htm" target="_blank">http://www.netload.in/dateiySgPP2b14W/1409...7ExpFut.pdf.htm</a>

转换:

http://www.netload.in/dateiySgPP2b14W/1409423417ExpFut.pdf.htm" target="_blank">http://www.netload.in/dateiySgPP2b14W/1409...7ExpFut.pdf.htm 

以下是代码:

function parse_urls($text, $maxurl_len = 35, $target = '_self') // Make URLs Clickable
{
    if (preg_match_all('/((ht|f)tps?:\/\/([\w\.]+\.)?[\w-]+(\.[a-zA-Z]{2,4})?[^\s\r\n\(\)"\'<>\,\!]+)/si', $text, $urls))
    {
        $offset1 = ceil(0.65 * $maxurl_len) - 2;

        $offset2 = ceil(0.30 * $maxurl_len) - 1;

        foreach (array_unique($urls[1]) AS $url)
        {
            if ($maxurl_len AND strlen($url) > $maxurl_len)
            {
                $urltext = substr($url, 0, $offset1) . '...' . substr($url, -$offset2);
            }
            else
            {
                $urltext = $url;
            }

            $text = str_replace($url, '<a href="'. $url .'" target="'. $target .'" title="'. $url .'">'. $urltext .'</a>', $text);
        }
    }

    return $text;
}

3 个答案:

答案 0 :(得分:2)

我把它扔到了一起。

<?php
function replaceUrlsWithLinks($text){
    $dom = new DOMDocument;
    $dom->loadXML($text);
    $xpath = new DOMXpath($dom);
    $query = $xpath->query('//text()[not(ancestor-or-self::a)]');
    foreach($query as $item){
        $content = $item->textContent;
        if(preg_match_all('/((ht|f)tps?:\/\/([\w\.]+\.)?[\w-]+(\.[a-zA-Z]{2,4})?[^\s\r\n\(\)"\'<>\,\!]+)/si',$content,$matches,PREG_SET_ORDER | PREG_OFFSET_CAPTURE)){
            foreach($matches as $match){
                $newA = $dom->createElement('a',$match[0][0]);
                $newA->setAttribute('href',$match[0][0]);
                $newA->setAttribute('target','_blank');
                $a = $item->splitText($match[0][1]);
                $b = $a->splitText(strlen($match[0][0]));
                $a->parentNode->replaceChild($newA,$a);
            }
        }
    }
    return $dom->saveHtml();
}
// The HTML to process ...
$html = <<<HTML
<block>
<a href="http://google.com">http://google.com</a>
<b>Stuff http://google.com</b>
asdf http://google.com ffaa 
</block>
HTML;
// Process the HTML and echo it out.
echo replaceUrlsWithLinks($html);
?>

输出结果为:

<block>
<a href="http://google.com">http://google.com</a>
<b>Stuff <a href="http://google.com" target="_blank">http://google.com</a></b>
asdf <a href="http://google.com" target="_blank">http://google.com</a> ffaa 
</block>

您不应该使用正则表达式来操纵HTML。

希望这有帮助。

凯尔

- 编辑 -

以前的代码效率更高,但如果您计划在同一父节点中有两个URL,则代码将因为DOM树已更改而中断。要解决此问题,您可以使用此更密集的代码:

<?php
function replaceUrlsWithLinks($text){
    $dom = new DOMDocument;
    $dom->loadXML($text);
    $xpath = new DOMXpath($dom);
    while(true){
        $shouldBreak = false;
        $query = $xpath->query('//text()[not(ancestor-or-self::a)]');
        foreach($query as $item){
            $shouldBreak = false;
            $content = $item->textContent;
            if(preg_match_all('/((ht|f)tps?:\/\/([\w\.]+\.)?[\w-]+(\.[a-zA-Z]{2,4})?[^\s\r\n\(\)"\'<>\,\!]+)/si',$content,$matches,PREG_SET_ORDER | PREG_OFFSET_CAPTURE)){
                foreach($matches as $match){
                    $newA = $dom->createElement('a',$match[0][0]);
                    $newA->setAttribute('href',$match[0][0]);
                    $newA->setAttribute('target','_blank');
                    $a = $item->splitText($match[0][1]);
                    $b = $a->splitText(strlen($match[0][0]));
                    $a->parentNode->replaceChild($newA,$a);
                    $shouldBreak = true;
                    break;
                }
            }
            if($shouldBreak == true)break;
        }
        if($shouldBreak == true){
            continue;
        }
        else {
            break;
        }
    }
    return $dom->saveHtml();
}

$html = <<<HTML
<block>
<a href="http://google.com">http://google.com</a>
<b>Stuff http://google.com</b>
asdf http://google.com ffaa  http://google.com
</block>
HTML;

echo replaceUrlsWithLinks($html);
?>

答案 1 :(得分:0)

此函数将http://www.domain.com之类的文本包含在锚标记中。我在这里看到的是你正在尝试将锚标签转换为锚标签,这当然是行不通的。所以:不要在你的文本中写下锚点,让脚本为你创建它们。

答案 2 :(得分:0)

当您尝试使用正则表达式解析HTML时,您正在遇到usual problems。您需要一个合适的HTML解析器。看看this thread