2010-03-15 5 views
3

내 웹 페이지에서 href HTML 링크를 모두 찾아서 'rel = "nofollow"를 추가하기 위해 RegEx 규칙을 작성하려고합니다.href 링크를 찾아서 NoFollow를 추가하는 RegEx 표현식

그러나 내 도메인 이름이있는 내부 링크가 제외되도록 (예 : ANY (와일드 카드) 내부 링크 (예 : pokerdiy.com)) 제외해야하는 URL 목록이 있습니다.

(+) (HREF = "HTTP를 : : 지금까지 작동되지 않는 http://www.example.com/link.aspx) 여기

내가 가진 무엇인가 - 예를 들어 - 나도 제외 목록에 정확한 URL을 지정할 수 있도록하려면 // 배경 화면이 필요하다면 전체 스레드와 요구 사항을 볼 수 있습니다. (위 부분은 건너 뛰십시오.) 전자 고기) : http://www.snapsis.com/Support/tabid/601/aff/9/aft/13117/afv/topic/afpgj/1/Default.aspx#14737

+1

하지 마십시오. http://www.codinghorror.com/blog/2009/11/parsing-html-the-cthulhu-way.html – TrueWill

+1

컴퓨터가 작동하지 않습니다! http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454 – dkarzon

+5

자, 첨부 파일을 읽고 요령을 얻었습니다. 그러나 제 요구 사항은 제한적이며 RegEx를 사용하여 구문 분석하는 것이 유일한 방법입니다. 다음에 감사드립니다. * 일반적으로 좋지 않습니다. (코딩 공포에서). 그 점을 염두에 두십시오. 제 RegEx 코드로 도움을받을 수있는 사람이 있습니까? 내가 왜 정규 표현식을 파싱 할 수 밖에 없는지를 설명 할 수는 있지만, 어쨌든 나쁜 생각이 들더라도 해결책은 필요하다. – Rodney

답변

2
(<a href="https?://)((?:(?!\b(pokerdiy.com|www\.example\.com/link\.aspx)\b)[^"])+)" 

http:// 또는 https://로 시작하고 어디에서나 href 속성의 pokerdiy.com 또는 www.example.com/link.aspx를 포함하지 않는 링크의 첫 번째 부분 일치합니다. rel="nofollow"가 이미 존재하여

\1\2" rel="nofollow" 

경우, 당신은이 두 가지로 오게 교체합니다. 그리고 물론 상대 링크 또는 ftp:// 등의 다른 프로토콜은 전혀 일치하지 않습니다.

설명 : 현재 위치에서 foo 또는 bar 일치 할 수 그것을하지 않는

(?!\b(foo|bar)\b)[^"]는 비 " 문자와 일치합니다. \b은 실수로 rebar 또는 foonly을 트리거하지 않도록합니다.

이 전체 구성은 ((?: ...)+) 반복되며 일치하는 항목은 역 참조 \2에 보존됩니다.

다음에 일치시킬 토큰은 "이므로 속성에 foo 또는 bar이있는 경우 전체 정규식이 실패합니다.

+0

팀 :이 공동체의 품질과 유용성은 결코 나를 놀라게하지 않습니다. - 정말 많은 답변을 해주셔서 감사합니다! 하나의 작은 문제가 있습니다 - 링크에 제목 태그 (또는 다른 것)가있는 경우 - a와 href 사이에이 표현식이 실패합니다 - 예 : target = "_ blank"href = "http://www.casinogamblingweb.com"은 일치하지 않습니다. 너는 a와 href 사이에 무엇이든있을 수 있도록 내가 도와 줄 수 있니? 또한 중복 된 nofollow 태그가 있음을 알고 있습니다. 이미 nofollow 태그가있는 경우 표현식 검사가 필요합니까? 감사합니다. – Rodney

+0

() +) (href = "https ?: // ((? :(?! \ b (pokerdiy.com | www \ .example \ .com/link \ .aspx) \ b [^ "]) +)" 및 $ 1 $ 2 $ 3 "rel ="nofollow " – Rodney

+0

그 것이 작동해야하며 정확히 내가 제안했을 것입니다. –

6

저는 앵커 태그에 이미 "rel ="이 있는지 여부를 감지 할 수있는 약간 더 강력한 버전을 개발 했으므로 속성을 복제하지 않습니다.

(<a\s*(?!.*\brel=)[^>]*)(href="https?://)((?!blog.bandit.co.nz)[^"]+)"([^>]*)> 

일치

<a href="http://google.com">Google</a> 
<a title="Google" href="http://google.com">Google</a> 
<a target="_blank" href="http://google.com">Google</a> 
<a href="http://google.com" title="Google" target="_blank">Google</a> 

그러나 일치하지 않는

<a rel="nofollow" href="http://google.com">Google</a> 
<a href="http://google.com" rel="nofollow">Google</a> 
<a href="http://google.com" rel="nofollow" title="Google" target="_blank">Google</a> 
<a href="http://google.com" title="Google" target="_blank" rel="nofollow">Google</a> 
<a href="http://google.com" title="Google" rel="nofollow" target="_blank">Google</a> 
<a target="_blank" href="http://blog.bandit.co.nz">Bandit</a> 

이 누군가를하는 데 도움이

$1$2$3"$4 rel="nofollow"> 

희망을 사용하여 교체!

제임스

+0

제임스 고맙습니다. – Rodney

10

제임스의 정규식에 대한 개선점은 :

(<a\s*(?!.*\brel=)[^>]*)(href="https?://)((?!(?:(?:www\.)?'.implode('|(?:www\.)?', $follow_list).'))[^"]+)"((?!.*\brel=)[^>]*)(?:[^>]*)> 

이 정규식 의지는 문자열 배열 $ follow_list에 링크를하지 일치합니다. 이 문자열에는 앞선 'www'가 필요 없습니다. :) 이 정규식은 태그의 다른 인수 (예 : target, style, title ...)를 보존한다는 점에서 이점이 있습니다.

$1$2$3"$4 rel="nofollow"> 

전체 예 (PHP) :하십시오 rel 인수가 이미 태그에있는 경우,

가와 교체 정규식이 일치하지 않습니다, 그래서 당신은하지 $의 follow_list의 URL에 다음과 강제 할 수

: 당신이 상관없이 rel을 덮어 쓰지하려면
function dont_follow_links($html) { 
// follow these websites only! 
$follow_list = array(
    'google.com', 
    'mypage.com', 
    'otherpage.com', 
); 
return preg_replace(
    '%(<a\s*(?!.*\brel=)[^>]*)(href="https?://)((?!(?:(?:www\.)?'.implode('|(?:www\.)?', $follow_list).'))[^"]+)"((?!.*\brel=)[^>]*)(?:[^>]*)>%', 
    '$1$2$3"$4 rel="nofollow">', 
    $html); 
} 

, 나는 콜백에서 rel 속성이 개별적으로 대체됩니다 preg_replace_callback 접근 방식을 사용

$subject = preg_replace_callback('%(<a\s*[^>]*href="https?://(?:(?!(?:(?:www\.)?'.implode('|(?:www\.)?', $follow_list).'))[^"]+)"[^>]*)>%', function($m) { 
    return preg_replace('%\srel\s*=\s*(["\'])(?:(?!\1).)*\1(\s|$)%', ' ', $m[1]).' rel="nofollow">'; 
}, $subject); 
+1

전설! 코드 샘플을 감사하십시오 :) –

+0

@para 사용자가 자신의'rel' 속성을 추가하지 못하게하려면 어떻게해야합니까? 나는'$ follow_list'에 나열되지 않은 링크를 따르지 않아야합니다. – alex

+1

@alex 나는 가장 쉬운 해결책으로 preg_replace_callback 접근법을 사용합니다. 그에 따라 내 대답을 업데이트했습니다. – para

관련 문제