cgi.escape кажется одним возможным выбором. Это хорошо работает? Есть ли что-то, что считается лучше?
Какой самый простой способ избежать HTML в Python?
Ответ 1
cgi.escape
в порядке. Он ускользает:
-
<
to<
-
>
to>
-
&
to&
Этого достаточно для всего HTML.
EDIT: Если у вас есть символы non-ascii, которые вы также хотите избежать, для включения в другой закодированный документ, который использует другую кодировку, например, говорит Крейг, просто используйте:
data.encode('ascii', 'xmlcharrefreplace')
Не забудьте сначала декодировать data
до unicode
, используя любую кодировку, которая была закодирована.
Однако по моему опыту такое кодирование бесполезно, если вы просто работаете с unicode
все время от начала. Просто закодируйте в конце кодировку, указанную в заголовке документа (utf-8
для максимальной совместимости).
Пример:
>>> cgi.escape(u'<a>bá</a>').encode('ascii', 'xmlcharrefreplace')
'<a>bá</a>
Также стоит отметить (спасибо Грегу) дополнительный параметр quote
cgi.escape
. Если он установлен в True
, cgi.escape
также избегает символов двойной кавычки ("
), поэтому вы можете использовать полученное значение в атрибуте XML/HTML.
EDIT: обратите внимание, что cgi.escape устарел в Python 3.2 в пользу html.escape
, который делает то же самое, за исключением того, что quote
по умолчанию - True.
Ответ 2
В Python 3.2 был представлен новый html
модуль, который используется для экранирования зарезервированных символов из разметки HTML.
У него есть одна функция escape()
:
>>> import html
>>> html.escape('x > 2 && x < 7')
'x > 2 && x < 7'
Ответ 3
Если вы хотите избежать HTML в URL-адресе:
Это, вероятно, НЕ то, что хотел OP (в вопросе явно не указано, в каком контексте подразумевается использование экранирования), но родная библиотека Python urllib имеет метод для удаления HTML-объектов, которые должны быть включены в URL-адрес безопасно.
Ниже приведен пример:
#!/usr/bin/python
from urllib import quote
x = '+<>^&'
print quote(x) # prints '%2B%3C%3E%5E%26'
Ответ 4
cgi.escape
должно быть хорошо, чтобы избежать HTML в ограниченном смысле избежания HTML-тегов и объектов символов.
Но вам, возможно, придется также рассмотреть проблемы с кодировкой: если HTML, который вы хотите процитировать, имеет символы, отличные от ASCII, в определенной кодировке, тогда вам также следует позаботиться о том, чтобы вы представляли их разумно при цитировании. Возможно, вы можете преобразовать их в объекты. В противном случае вы должны убедиться, что правильные преобразования кодирования выполняются между "исходным" HTML и страницей, в которую он встроен, чтобы не повредить символы, отличные от ASCII.
Ответ 5
Существует также превосходный пакет markupsafe.
>>> from markupsafe import Markup, escape
>>> escape("<script>alert(document.cookie);</script>")
Markup(u'<script>alert(document.cookie);</script>')
Пакет markupsafe
хорошо спроектирован и, возможно, самый универсальный и Pythonic способ избежать, IMHO, потому что:
- return (
Markup
) - это класс, производный от Unicode (то естьisinstance(escape('str'), unicode) == True
- он правильно обрабатывает ввод Unicode
- это работает в Python (2.6, 2.7, 3.3 и pypy)
- он учитывает пользовательские методы объектов (т.е. объекты со свойством
__html__
) и перегрузки шаблона (__html_format__
).
Ответ 6
Нет библиотек, чистый Python, безопасно экранирует текст в HTML-текст:
text.replace('&', '&').replace('>', '>').replace('<', '<'
).encode('ascii', 'xmlcharrefreplace')
Ответ 7
cgi.escape
extended
Эта версия улучшает cgi.escape
. Он также сохраняет пробелы и символы новой строки. Возвращает строку unicode
.
def escape_html(text):
"""escape strings for display in HTML"""
return cgi.escape(text, quote=True).\
replace(u'\n', u'<br />').\
replace(u'\t', u' ').\
replace(u' ', u' ')
например
>>> escape_html('<foo>\nfoo\t"bar"')
u'<foo><br />foo "bar"'
Ответ 8
Не самый простой способ, но все же простой. Основное отличие от cgi.escape модуля - оно по-прежнему будет работать правильно, если в тексте уже есть &
. Как вы видите из комментариев к нему:
cgi.escape version
def escape(s, quote=None):
'''Replace special characters "&", "<" and ">" to HTML-safe sequences.
If the optional flag quote is true, the quotation mark character (")
is also translated.'''
s = s.replace("&", "&") # Must be done first!
s = s.replace("<", "<")
s = s.replace(">", ">")
if quote:
s = s.replace('"', """)
return s
регулярная версия
QUOTE_PATTERN = r"""([&<>"'])(?!(amp|lt|gt|quot|#39);)"""
def escape(word):
"""
Replaces special characters <>&"' to HTML-safe sequences.
With attention to already escaped characters.
"""
replace_with = {
'<': '>',
'>': '<',
'&': '&',
'"': '"', # should be escaped in attributes
"'": ''' # should be escaped in attributes
}
quote_pattern = re.compile(QUOTE_PATTERN)
return re.sub(quote_pattern, lambda x: replace_with[x.group(0)], word)
Ответ 9
Через BeautifulSoup4:
>>> bs4.dammit import EntitySubstitution
>>> esub = EntitySubstitution()
>>> esub.substitute_html("r&d")
'r&d'