Коротка версія!
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)
Джерело Regex: MarkupSafe . Їх версія також обробляє HTML-об'єкти, а ця швидка - ні.
Чому я не можу просто зняти теги і залишити їх?
Одна річ - утримати людей від <i>italicizing</i>
речей, не залишаючи i
плавати навколо. Але інше - взяти довільне введення та зробити його абсолютно нешкідливим. Більшість методів на цій сторінці залишатимуть такі речі, як незакриті коментарі ( <!--
) та кутові дужки, які не входять до тегів ( blah <<<><blah
). Версія HTMLParser може навіть залишати повні теги в тому випадку, якщо вони знаходяться всередині незакритого коментаря.
Що робити, якщо ваш шаблон {{ firstname }} {{ lastname }}
? firstname = '<a'
і lastname = 'href="http://evil.com/">'
буде пропущений кожним знімачем тегів на цій сторінці (за винятком @Medeiros!), оскільки вони не є повноцінними тегами самостійно. Видалення нормальних тегів HTML недостатньо.
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 та інші утиліти html з останньої версії хороші, але я вважаю їх менш зручними, ніж MarkupSafe. Вони досить автономні, ви можете скопіювати все, що вам потрібно, з цього файлу .
Якщо вам потрібно зняти майже всі теги, бібліотека Bleach - це добре. Ви можете дозволити йому виконувати правила типу "мої користувачі можуть робити курсив, але вони не можуть створювати рамки кадрів".
Зрозумійте властивості знімача тегів! Виконайте на ньому нечіткі тести! Ось код, який я використовував для дослідження для цієї відповіді.
ovish Примітка - саме питання стосується друку на консоль, але це найкращий результат Google для "python strip html from string", тому саме ця відповідь на 99% стосується Інтернету.
&
). Ви можете 1) видалити їх разом із тегами (часто небажаними та непотрібними, оскільки вони еквівалентні звичайному тексту), 2) залишити їх незмінними (підходяще рішення, якщо відрізаний текст повернеться назад у контекст HTML) або 3 ) розшифруйте їх до простого тексту (якщо зрізаний текст переходить у базу даних чи інший не HTML-контекст, або якщо ваш веб-фреймворк автоматично виконує HTML-текст для вас).