Короткая версия!
import re, cgi
tag_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
# Remove well-formed tags, fixing mistakes by legitimate users
no_tags = tag_re.sub('', user_input)
# Clean up anything else by escaping
ready_for_web = cgi.escape(no_tags)
Источник регулярных выражений: MarkupSafe . Их версия также обрабатывает HTML-сущности, а эта быстрая - нет.
Почему я не могу просто раздеть теги и оставить его?
Одно дело удерживать людей от <i>italicizing</i>
вещей, не оставляя i
с плавающей вокруг. Но это другой способ принять произвольный вклад и сделать его совершенно безвредным. Большинство методов на этой странице оставят нетронутыми такие вещи, как закрытые комментарии (<!--
) и угловые скобки, которые не являются частью тегов (blah <<<><blah
). Версия HTMLParser может даже оставлять полные теги, если они находятся внутри закрытого комментария.
Что если ваш шаблон {{ firstname }} {{ lastname }}
? firstname = '<a'
и lastname = 'href="http://evil.com/">'
будут пропущены каждым стриптизером тегов на этой странице (кроме @Medeiros!), Потому что они не являются полными тегами самостоятельно. Недостаточно удалить обычные HTML-теги.
Django's strip_tags
, улучшенная (см. Следующий заголовок) версия главного ответа на этот вопрос, выдает следующее предупреждение:
Абсолютно НЕТ гарантии, что полученная строка безопасна для HTML. Поэтому НИКОГДА не помечайте как безопасный результат strip_tags
вызова, не экранируя его первым, например, escape()
.
Следуйте их советам!
Чтобы удалить теги с HTMLParser, вы должны запустить его несколько раз.
Легко обойти главный ответ на этот вопрос.
Посмотрите на эту строку ( источник и обсуждение ):
<img<!-- --> src=x onerror=alert(1);//><!-- -->
Когда HTMLParser видит его впервые, он не может сказать, что <img...>
является тегом. Он выглядит разбитым, поэтому HTMLParser не избавится от него. Вынимается только <!-- comments -->
, а вам остается
<img src=x onerror=alert(1);//>
Эта проблема была раскрыта проекту Django в марте 2014 года. Их старый strip_tags
был по сути тем же, что и главный ответ на этот вопрос. Их новая версия в основном запускает его в цикле, пока повторный запуск не изменит строку:
# _strip_once runs HTMLParser once, pulling out just the text of all the nodes.
def strip_tags(value):
"""Returns the given HTML with all tags stripped."""
# Note: in typical case this loop executes _strip_once once. Loop condition
# is redundant, but helps to reduce number of executions of _strip_once.
while '<' in value and '>' in value:
new_value = _strip_once(value)
if len(new_value) >= len(value):
# _strip_once was not able to detect more tags
break
value = new_value
return value
Конечно, это не проблема, если вы всегда избегаете результата strip_tags()
.
Обновление 19 марта 2015 г. : в версиях Django до 1.4.20, 1.6.11, 1.7.7 и 1.8c1 была ошибка. Эти версии могут ввести бесконечный цикл в функцию strip_tags (). Исправленная версия воспроизводится выше. Подробнее здесь .
Хорошие вещи для копирования или использования
Мой пример кода не обрабатывает сущности HTML, как это делают упакованные версии Django и MarkupSafe.
Мой пример кода взят из превосходной библиотеки MarkupSafe для предотвращения межсайтовых скриптов. Это удобно и быстро (с ускорением C до его родной версии Python). Он включен в Google App Engine и используется Jinja2 (2.7 и выше) , Mako, Pylons и другими. Он легко работает с шаблонами Django из Django 1.7.
Django's strip_tags и другие html-утилиты из последней версии хороши, но я считаю их менее удобными, чем MarkupSafe. Они довольно автономны, вы можете скопировать все, что вам нужно, из этого файла .
Если вам нужно удалить почти всех тегов, библиотека Bleach хороша. Вы можете заставить его применять правила, такие как «мои пользователи могут выделять курсивом, но они не могут создавать фреймы».
Поймите свойства вашего стриптизерши! Запустите пушистые тесты на нем! Вот код Я использовал для исследования этого ответа.
зову примечание - Сам вопрос касается печати на консоль, но это лучший результат Google для "python strip html from string", поэтому этот ответ на 99% относится к сети.