2012-07-19 52 views
1

我试图用相对关闭所有外部URL =“nofollow的” parametr:Django的中间件添加relnofollow所有外部链接

我写这个简单的中间件:

import re 

NOFOLLOW_RE = re.compile(u'<a (?![^>]*rel=["\']nofollow[\'"])'\ 
         u'(?![^>]*href=["\']mysite\.com[\'"])', 
         re.UNICODE|re.IGNORECASE) 

class NofollowLinkMiddleware(object): 

    def process_response(self, request, response): 
     if ("text" in response['Content-Type']): 

      response.content = re.sub(NOFOLLOW_RE, u'<a rel="nofollow" ', response.content.decode('UTF8')) 
      return response 
     else: 
      return response 

它的工作原理,但关闭内部和外部的所有链接。并且我不知道如何添加<noindex> </noindex >标记链接。

+4

这种方法是一场噩梦。不要这样做! – 2012-07-19 14:44:14

+0

为什么?似乎它工作得很快/ – mikhail 2012-07-21 10:36:25

+0

原因中间件使用正则表达式处理每个响应主体,添加额外的CPU负载。随着页面内容的增长,它会吃得更多。你确定你的正则表达式会正确处理新内容吗?你应该正确地写出你的模板,避免发明新的自行车。 – 2012-07-21 19:51:06

回答

3

首先,你忘了'http://'和url路径。所以,你的正则表达式应该是:

NOFOLLOW_RE = re.compile(u'<a (?![^>]*rel=["\']nofollow[\'"])'\ 
         u'(?![^>]*href=["\']http://mysite\.com(/[^\'"]*)?[\'"])', 
         re.U|re.I) 

然后,你还需要考虑从“/”开始的HREF和“#”的内部链接:

NOFOLLOW_RE = re.compile(u'<a (?![^>]*rel=["\']nofollow[\'"])'\ 
         u'(?![^>]*href=["\'](?:https?://mysite\.com(?:/[^\'"]*)|/[^\'"]*|#[^\'"]*)[\'"])', 
         re.U|re.I) 

此外,你可能希望考虑第三级域名和“https://”协议。

对于<NOINDEX>标签,你可以使用组,看看re.sub() in Python docs

NOFOLLOW_RE = re.compile(u'<a (?P<link>(?![^>]*rel=["\']nofollow[\'"])'\ 
         u'(?![^>]*href=["\'](?:https?://mysite\.com(?:/[^\'"]*)|/[^\'"]*|#[^\'"]*)[\'"]).*?</a>)', 
         re.U|re.I) 
... 
response.content = NOFOLLOW_RE.sub(u'<noindex><a rel="nofollow" \g<link></noindex>', your_html) 

这正则表达式是古怪。我强烈建议你为它编写一个测试,以及所有可能的<和>标记的组合以及它可以想象的属性。如果您之后在此代码中发现了一些问题,测试将帮助您不会破坏所有内容。

0

我知道我很晚了,但我正在为别人留下答案。 @HighCat除了一个以外,都给出了正确的答案。上述正则表达式也将增加对nofollow的链接http://example.com

在这种情况下,正则表达式所以应该是=>

import re 

NOFOLLOW_RE = re.compile(u'<a (?P<link>(?![^>]*rel=["\']nofollow[\'"])'\ 
         u'(?![^>]*href=["\'](?:https?://example\.com/?(?:[^\'"]*)|/[^\'"]*|#[^\'"]*)[\'"]).*?</a>)', 
         re.U|re.I) 

class NofollowLinkMiddleware(object): 

    def process_response(self, request, response): 
     if ("text" in response['Content-Type']): 

      response.content = NOFOLLOW_RE.sub(u'<a rel="nofollow" target="_blank" \g<link>', response.content.decode('UTF8')) 
      return response 
     else: 
      return response 

是轻微的变化。我应该评论或编辑,但我没有足够的声誉(评论)和编辑也需要6 +字符更改。

相关问题