投稿内容の外部リンクのみにnofollow
属性を追加したいです。内部リンクはfollow
のままにします。
それで、外部リンクだけをフォローしないようにするためにwp_rel_nofollow()
を使うことができますか?それとも他の方法を使う必要がありますか?
wp_rel_nofollow()
はすべてのリンクにnofollow属性を追加しますので、使用できないかどうかわからないかもしれません。
この関数を使って、すべての外部リンクにrel="nofollow"
を追加することができます。この機能はあなたのブログ/ウェブサイトのURL(内部ドメインとして)に対してコンテンツ内のすべてのリンクをチェックし、両方が一致しない場合はnofollow属性を追加します。
function add_nofollow_external_links( $content ) {
return preg_replace_callback( '/<a>]+/', 'auto_nofollow_callback', $content );
}
function auto_nofollow_callback( $matches ) {
$link = $matches[0];
$site_link = get_bloginfo('url');
if (strpos($link, 'rel') === false) {
$link = preg_replace("%(href=S(?!$site_link))%i", 'rel="nofollow" $1', $link);
} elseif (preg_match("%href=S(?!$site_link)%i", $link)) {
$link = preg_replace('/rel=S(?!nofollow)S*/i', 'rel="nofollow"', $link);
}
return $link;
}
add_filter( 'the_content', 'add_nofollow_external_links' );
未検証。
@Robert色相の答えとワードプレス関数 wp_rel_nofollow() と wp_rel_nofollow_callback に基づいて、私はこのために働くこの非常によく似た解決策を思いついた。何らかの理由でRobertがnofollow属性をリンクに追加しなかったからです。
function add_rel_nofollow( $text ) {
// This is a pre save filter, so text is already escaped.
$text = stripslashes($text);
$text = preg_replace_callback('|<a (.+?)>|i', 'add_rel_nofollow_callback', $text);
//$text = wp_slash($text); //I had to remove this because it was adding undesired backslashes to the output
return $text;
}
function add_rel_nofollow_callback( $matches ) {
$text = $matches[1];
$site_link = get_bloginfo('url');
if (strpos($text, 'rel') === false) {
$text = preg_replace("%(href=S(?!$site_link))%i", 'rel="nofollow" $1', $text);
} elseif (preg_match("%href=S(?!$site_link)%i", $link)) {
$text = str_replace(array(' rel="nofollow"', " rel='nofollow'"), '', $text);
}
return "<a $text rel=\"nofollow\">";
}
add_filter( 'the_content', 'add_rel_nofollow' );
これにより、以前に公開されたすべての投稿と将来の投稿にrel="nofollow"
属性が追加されます。
パフォーマンスに関しては、私は@Roberthueに同じ質問をしましたが、これが彼の言ったことです。
私はそれがなぜあるべきかわからない。 wp_rel_nofollow()を使用するのとほとんど同じですが、外部ドメインの追加チェックがあります。これで終わりですが、チェックして除外するために大量のドメインを追加すると、おそらくそうなるでしょう。 - ロバート色相
GixtyのコードもRobertのコードも私にとってはうまくいきませんでした。 Robertのものは正しくリンクにもマッチしませんでした、そして正しいパターンでさえリンクが内部か外部かをチェックせず、そしてすべてのリンクにnofollowを追加しました、一方Gixtyのものは正しくnofollowを追加しました内部のものだけではありません。
これは私のコードです。これは私には問題なく動作し、rel nofollowを内部リンクに追加するだけです。また、rel属性を持っているリンクには関係ありません。どのような値でも構いません。
function add_nofollow_external_links( $content ) {
return preg_replace_callback( '|<a (.+?)>|i', 'add_nofollow_callback', $content );
}
function add_nofollow_callback( $matches ) {
$text = $matches[1];
$site_link = get_bloginfo( 'url' );
//If this is an internal link, don't touch it
if( strpos( $text, $site_link ) ) {
return "<a $text>";
}
//If this doesn't have the rel attribute, append the nofollow
if( strpos( $text, 'rel' ) === false ) {
$text = preg_replace( "%(href=S(?!$site_link))%i", 'rel="nofollow" $1', $text );
}
return "<a $text rel=\"nofollow\">";
}
以下のコードを使用して、すべての外部リンクをフォローしないようにしています。このコードは機能します。
add_filter('the_content', 'my_nofollow');
add_filter('the_excerpt', 'my_nofollow');
function my_nofollow($content) {
return preg_replace_callback('/<a[^>]+/', 'my_nofollow_callback', $content);
}
function my_nofollow_callback($matches) {
$link = $matches[0];
$site_link = get_bloginfo('url');
if (strpos($link, 'rel') === false) {
$link = preg_replace("%(href=\S(?!$site_link))%i", 'rel="nofollow" $1', $link);
} elseif (preg_match("%href=\S(?!$site_link)%i", $link)) {
$link = preg_replace('/rel=\S(?!nofollow)\S*/i', 'rel="nofollow"', $link);
}
return $link;
}
以下の関数を使ってnofollow
タグを外部リンクに追加します。
add_filter( 'the_content', 'nofollow_enternal_links');
function nofollow_enternal_links( $content ) {
$regexp = "<a\s[^>]*href=(\"??)([^\" >]*?)\\1[^>]*>";
if(preg_match_all("/$regexp/siU", $content, $matches, PREG_SET_ORDER)) {
if( !empty($matches) ) {
$srcUrl = get_option('home');
for ($i=0; $i < count($matches); $i++)
{
$tag = $matches[$i][0];
$tag2 = $matches[$i][0];
$url = $matches[$i][0];
$noFollow = '';
$pattern = '/rel\s*=\s*"\s*[n|d]ofollow\s*"/';
preg_match($pattern, $tag2, $match, PREG_OFFSET_CAPTURE);
if( count($match) < 1 )
$noFollow .= ' rel="nofollow" ';
$pos = strpos($url,$srcUrl);
if ($pos === false) {
$tag = rtrim ($tag,'>');
$tag .= $noFollow.'>';
$content = str_replace($tag2,$tag,$content);
}
}
}
}
$content = str_replace(']]>', ']]>', $content);
return $content;
}
これはサイト全体で機能し、公開されているものも含めてすべての投稿をターゲットにしています。
このアプローチは他の投稿されたものとは異なります。
私はこれを投稿していますが、これが他のアプローチの方がパフォーマンスに優れているかどうかを誰かが確認できるかどうかを確認するためです。
他の答えはすべての場合にうまくいくとは限りません、そして/またはrel
属性が存在しているかどうかを確かめるべきではない場合や信頼できない場合はリンクを変更します。
このソリューションはもう少し包括的で、より柔軟性があります。
// Takes an string of html attr and adds an attribute value; if attr is present and $replace=false, space and the new value is added to end of the attribute; otherwise attr is added to end.
function inject_html_attr($attr_str, $new_attr_name, $attr_value, $replace=false) {
return preg_replace_callback(
'/(((?:^|\s)'.$new_attr_name.'=[\'"])(.*?))([\'"])|$/i',
function($m)use($new_attr_name,$attr_value, $replace){
if( $m[0] ){
$m[1] = $replace ? $m[2] : $m[1].($m[3]?' ':'');
}else{
$m[1] = ' '.$new_attr_name.'="';
$m[4] = '"';
}
return $m[1].$attr_value.$m[4];
},
$attr_str, 1 );
}
add_filter('the_content', 'apply_external_link_markup');
function apply_external_link_markup($content) {
// Assumes attributes are quoted (single or double)
return preg_replace_callback(
'/<a ([^>]*)(href=(["\'])(?:https?:)?\\/\\/([^\\/\'">]+)(.*?)\3)([^>]*)>/i',
function($m) {
if( $m[4] === $_SERVER['HTTP_Host'] )
return $m[0];
$attr = ' '.trim(trim($m[1]).' '.trim($m[6]));
//$attr = inject_html_attr( $attr, 'class', 'external-link' );
//$attr = inject_html_attr( $attr, 'target', '_blank', true );
$attr = inject_html_attr( $attr, 'rel', 'nofollow', true );
return '<a '.$m[2].$attr.'>';
},
$content );
}