Промежуточное ПО Django для добавления relnofollow для всех внешних ссылок
Я пытаюсь закрыть все внешние URL с параметром rel="nofollow":
Я пишу это простое промежуточное ПО:
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
это работает, но закрывает все ссылки внутренние и внешние. И я не знаю, как еще добавить тег
2 ответа
Сначала вы забыли "http://" и URL-путь. Итак, вы regexp должны быть:
NOFOLLOW_RE = re.compile(u'<a (?![^>]*rel=["\']nofollow[\'"])'\
u'(?![^>]*href=["\']http://mysite\.com(/[^\'"]*)?[\'"])',
re.U|re.I)
Затем вы также должны рассматривать hrefs, начинающиеся с "/" и "#", как внутренние ссылки:
NOFOLLOW_RE = re.compile(u'<a (?![^>]*rel=["\']nofollow[\'"])'\
u'(?![^>]*href=["\'](?:https?://mysite\.com(?:/[^\'"]*)|/[^\'"]*|#[^\'"]*)[\'"])',
re.U|re.I)
Также вы, возможно, захотите принять во внимание домен 3-го уровня и протокол "https://".
Для тега
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)
Это регулярное выражение является странным. Я настоятельно рекомендую вам написать тест со всеми возможными комбинациями тегов и их атрибутов, которые вы можете себе представить. Если после этого вы обнаружите какую-то проблему в этом коде, тест поможет вам не все сломать.
Я знаю, что я очень поздно, но я оставляю ответ за других. @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+ символов.