我需要找到一种方法来阅读用户发布的内容,以查找可能已包含的任何超链接,创建锚标记,将target和rel = nofollow属性添加到所有这些链接。
我遇到过一些像这样的REGEX解决方案:
(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))
但是在关于同一问题的其他问题上,强烈建议 NOT 使用REGEX而不是PHP的DOMDocument
。
无论什么是最好的方式,我需要添加一些如上所述的属性,以加强网站上的所有外部链接。
答案 0 :(得分:1)
您可能对Goutte感兴趣 你可以定义自己的过滤器等。
答案 1 :(得分:1)
首先,您提到的指南建议不要使用正则表达式解析 HTML 。据我了解,您要做的是解析用户的纯文本并将其转换为HTML 。为此目的,正则表达式通常都很好。
(请注意,我假设您自己将文本解析为链接,并且不使用外部库。在后一种情况下,您需要修复HTML库输出,为此您< em>应使用DOMDocument
迭代所有<a>
标记并添加适当的属性。)
现在,您可以通过两种方式解析它:服务器端或客户端。
优点:
缺点:
rel="nofollow"
属性,以便不遵循链接。优点:
rel="nofollow"
属性,因为他们首先看不到链接 - 他们是通过Javascript生成的,机器人通常不会#&# 39;解析Javascript。缺点:
我将专注于在服务器端实施它。
因此,为了解析用户输入的链接并添加任何您想要的属性,您可以使用以下内容:
<?php
function replaceLinks($text)
{
$regex = '/'
. '(?<!\S)'
. '(((ftp|https?)?:?)\/\/|www\.)'
. '(\S+?)'
. '(?=$|\s|[,]|\.\W|\.$)'
. '/m';
return preg_replace_callback($regex, function($match)
{
return '<a'
. ' target=""'
. ' rel="nofollow"'
. ' href="' . $match[0] . '">'
. $match[0]
. '</a>';
}, $text);
}
说明:
(?<!\S)
:前面没有非空白字符。(((ftp|https?)?:?)\/\/|www\.)
:接受ftp://
,http://
,https://
,://
,//
和www.
作为网址的开头。 (\S+?)
以非贪婪的方式匹配所有非空白的内容。(?=$|\s|[,]|\.\W|\.$)
每个网址必须跟在行尾,空格,逗号,点后跟\w
以外的字符(这是为了允许.com
,{{ 1}}等匹配)或点后跟行尾。.co.jp
flag - 匹配多行文字。现在,为了支持我声称它有效,我添加了一些测试用例:
m
每个测试用例由两部分组成:源输入和预期输出。我使用以下代码来确定函数是否通过了上述测试:
$tests = [];
$tests []= ['http://example.com', '<a target="" rel="nofollow" href="http://example.com">http://example.com</a>'];
$tests []= ['https://example.com', '<a target="" rel="nofollow" href="https://example.com">https://example.com</a>'];
$tests []= ['ftp://example.com', '<a target="" rel="nofollow" href="ftp://example.com">ftp://example.com</a>'];
$tests []= ['://example.com', '<a target="" rel="nofollow" href="://example.com">://example.com</a>'];
$tests []= ['//example.com', '<a target="" rel="nofollow" href="//example.com">//example.com</a>'];
$tests []= ['www.example.com', '<a target="" rel="nofollow" href="www.example.com">www.example.com</a>'];
$tests []= ['user@www.example.com', 'user@www.example.com'];
$tests []= ['testhttp://example.com', 'testhttp://example.com'];
$tests []= ['example.com', 'example.com'];
$tests []= [
'test http://example.com',
'test <a target="" rel="nofollow" href="http://example.com">http://example.com</a>'];
$tests []= [
'multiline' . PHP_EOL . 'blah http://example.com' . PHP_EOL . 'test',
'multiline' . PHP_EOL . 'blah <a target="" rel="nofollow" href="http://example.com">http://example.com</a>' . PHP_EOL . 'test'];
$tests []= [
'text //example.com/slashes.php?parameters#fragment, some other text',
'text <a target="" rel="nofollow" href="//example.com/slashes.php?parameters#fragment">//example.com/slashes.php?parameters#fragment</a>, some other text'];
$tests []= [
'text //example.com. new sentence',
'text <a target="" rel="nofollow" href="//example.com">//example.com</a>. new sentence'];
我认为这可以让您了解如何解决问题。随意添加更多测试并使用正则表达式进行实验,以使其适合您的特定需求。
答案 2 :(得分:0)
使用jquery获取要发布的内容并在将其发布到PHP之前对其进行处理。
$('#idof_content').val(
$('#idof_content').val().replace(/\b(http(s|):\/\/|)(www\.\S+)/ig,
"<a href='http\$2://\$3' target='_blank' rel='nofollow'>\$3</a>"));