Intereting Posts
PHP Websocket аутентифицирует пользователя в тесте (pass session cookie) Что такое хороший Ruby on Rails и PHP-хостинг? Почему PHP не видит строку запроса? Как прочитать таблицу на Google Диске в PHP? правильный способ выхода из сеанса в PHP передача атрибутов href на другую php-страницу алгоритм для преобразования md5 (или, может быть, другой метод хэширования?) в целое число, где можно установить возможные результирующие целые диапазоны (например: 1-10000)? Добавление Node.js (для уведомлений в режиме реального времени) к существующему PHP-приложению Атрибуты поля объекта Symfony 2 Как отключить определенную сессию php при выходе из системы загрузить изображение php с помощью src PHP GD Используйте одно изображение для маскировки другого изображения, включая прозрачность Преобразование аудиофайлов в PHP Как запустить профайлер XDebug для скрипта PHP в командной строке? Ограничить выполнение PHP?

Как добавить rel = "nofollow" к ссылкам с preg_replace ()

Нижеприведенная функция предназначена для применения rel="nofollow" для всех внешних ссылок и внутренних ссылок, если только путь не соответствует предопределенному корневому URL-адресу, определенному как $my_folder ниже.

Поэтому, учитывая переменные …

 $my_folder = 'http://localhost/mytest/go/'; $blog_url = 'http://localhost/mytest'; 

И контент …

 <a href="http://localhost/mytest/">internal</a> <a href="http://localhost/mytest/go/hostgator">internal cloaked link</a> <a href="http://cnn.com">external</a> 

Конечный результат, после замены должен быть …

 <a href="http://localhost/mytest/">internal</a> <a href="http://localhost/mytest/go/hostgator" rel="nofollow">internal cloaked link</a> <a href="http://cnn.com" rel="nofollow">external</a> 

Обратите внимание, что первая ссылка не изменяется, так как ее внутренняя ссылка.

Ссылка на второй строке также является внутренней ссылкой, но поскольку она соответствует нашей строке $my_folder , она также получает nofollow .

Третья ссылка самая простая, так как она не соответствует blog_url , ее явно внешней ссылке.

Однако в приведенном ниже скрипте ВСЕ мои ссылки получают nofollow . Как я могу исправить скрипт, чтобы делать то, что хочу?

 function save_rseo_nofollow($content) { $my_folder = $rseo['nofollow_folder']; $blog_url = get_bloginfo('url'); preg_match_all('~<a.*>~isU',$content["post_content"],$matches); for ( $i = 0; $i <= sizeof($matches[0]); $i++){ if ( !preg_match( '~nofollow~is',$matches[0][$i]) && (preg_match('~' . $my_folder . '~', $matches[0][$i]) || !preg_match( '~'.$blog_url.'~',$matches[0][$i]))){ $result = trim($matches[0][$i],">"); $result .= ' rel="nofollow">'; $content["post_content"] = str_replace($matches[0][$i], $result, $content["post_content"]); } } return $content; } 

Попытайтесь сделать его более читаемым в первую очередь, и только после этого сделайте ваши правила if более сложными:

 function save_rseo_nofollow($content) { $content["post_content"] = preg_replace_callback('~<(a\s[^>]+)>~isU', "cb2", $content["post_content"]); return $content; } function cb2($match) { list($original, $tag) = $match; // regex match groups $my_folder = "/hostgator"; // re-add quirky config here $blog_url = "http://localhost/"; if (strpos($tag, "nofollow")) { return $original; } elseif (strpos($tag, $blog_url) && (!$my_folder || !strpos($tag, $my_folder))) { return $original; } else { return "<$tag rel='nofollow'>"; } } 

Дает следующий результат:

 [post_content] => <a href="http://localhost/mytest/">internal</a> <a href="http://localhost/mytest/go/hostgator" rel=nofollow>internal cloaked link</a> <a href="http://cnn.com" rel=nofollow>external</a> 

Проблема в вашем исходном коде могла бы быть $ rseo, которая не была объявлена ​​нигде.

Вот решение DOMDocument …

 $str = '<a href="http://localhost/mytest/">internal</a> <a href="http://localhost/mytest/go/hostgator">internal cloaked link</a> <a href="http://cnn.com" rel="me">external</a> <a href="http://google.com">external</a> <a href="http://example.com" rel="nofollow">external</a> <a href="http://stackoverflow.com" rel="junk in the rel">external</a> '; $dom = new DOMDocument(); $dom->preserveWhitespace = FALSE; $dom->loadHTML($str); $a = $dom->getElementsByTagName('a'); $host = strtok($_SERVER['HTTP_HOST'], ':'); foreach($a as $anchor) { $href = $anchor->attributes->getNamedItem('href')->nodeValue; if (preg_match('/^https?:\/\/' . preg_quote($host, '/') . '/', $href)) { continue; } $noFollowRel = 'nofollow'; $oldRelAtt = $anchor->attributes->getNamedItem('rel'); if ($oldRelAtt == NULL) { $newRel = $noFollowRel; } else { $oldRel = $oldRelAtt->nodeValue; $oldRel = explode(' ', $oldRel); if (in_array($noFollowRel, $oldRel)) { continue; } $oldRel[] = $noFollowRel; $newRel = implode($oldRel, ' '); } $newRelAtt = $dom->createAttribute('rel'); $noFollowNode = $dom->createTextNode($newRel); $newRelAtt->appendChild($noFollowNode); $anchor->appendChild($newRelAtt); } var_dump($dom->saveHTML()); 

Вывод

 string(509) "<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> <html><body> <a href="http://localhost/mytest/">internal</a> <a href="http://localhost/mytest/go/hostgator">internal cloaked link</a> <a href="http://cnn.com" rel="me nofollow">external</a> <a href="http://google.com" rel="nofollow">external</a> <a href="http://example.com" rel="nofollow">external</a> <a href="http://stackoverflow.com" rel="junk in the rel nofollow">external</a> </body></html> " 

Попробуйте это (PHP 5.3+):

  • пропустить выбранный адрес
  • разрешить вручную установить параметр rel

и код:

 function nofollow($html, $skip = null) { return preg_replace_callback( "#(<a[^>]+?)>#is", function ($mach) use ($skip) { return ( !($skip && strpos($mach[1], $skip) !== false) && strpos($mach[1], 'rel=') === false ) ? $mach[1] . ' rel="nofollow">' : $mach[0]; }, $html ); } 

Примеры:

 echo nofollow('<a href="link somewhere" rel="something">something</a>'); // will be same because it's already contains rel parameter echo nofollow('<a href="http://www.cnn.com">something</a>'); // ad // add rel="nofollow" parameter to anchor echo nofollow('<a href="http://localhost">something</a>', 'localhost'); // skip this link as internall link 

Использование регулярных выражений для правильной работы должно быть довольно сложным. Было бы проще использовать фактический парсер, например, один из расширения DOM . DOM не очень удобен для начинающих, поэтому вы можете загружать HTML с помощью DOM и запускать модификации с помощью SimpleXML . Они поддерживаются одной и той же библиотекой, поэтому ее легко использовать с другой.

Вот как это может выглядеть:

 $my_folder = 'http://localhost/mytest/go/'; $blog_url = 'http://localhost/mytest'; $html = '<html><body> <a href="http://localhost/mytest/">internal</a> <a href="http://localhost/mytest/go/hostgator">internal cloaked link</a> <a href="http://cnn.com">external</a> </body></html>'; $dom = new DOMDocument; $dom->loadHTML($html); $sxe = simplexml_import_dom($dom); // grab all <a> nodes with an href attribute foreach ($sxe->xpath('//a[@href]') as $a) { if (substr($a['href'], 0, strlen($blog_url)) === $blog_url && substr($a['href'], 0, strlen($my_folder)) !== $my_folder) { // skip all links that start with the URL in $blog_url, as long as they // don't start with the URL from $my_folder; continue; } if (empty($a['rel'])) { $a['rel'] = 'nofollow'; } else { $a['rel'] .= ' nofollow'; } } $new_html = $dom->saveHTML(); echo $new_html; 

Как вы можете видеть, это очень коротко и просто. В зависимости от ваших потребностей вы можете использовать preg_match() вместо объектов strpos() , например:

  // change the regexp to your own rules, here we match everything under // "http://localhost/mytest/" as long as it's not followed by "go" if (preg_match('#^http://localhost/mytest/(?!go)#', $a['href'])) { continue; } 

Заметка

Я пропустил последний блок кода в OP, когда впервые прочитал вопрос. Код, который я опубликовал (и в основном любое решение на основе DOM), лучше подходит для обработки целой страницы, а не блока HTML. В противном случае DOM попытается «исправить» ваш HTML и может добавить <body> , DOCTYPE и т. Д. …

 <? $str='<a href="http://localhost/mytest/">internal</a> <a href="http://localhost/mytest/go/hostgator">internal cloaked link</a> <a href="http://cnn.com">external</a>'; function test($x){ if (preg_match('@localhost/mytest/(?!go/)@i',$x[0])>0) return $x[0]; return 'rel="nofollow" '.$x[0]; } echo preg_replace_callback('/href=[\'"][^\'"]+/i', 'test', $str); ?>