Какой самый простой способ избежать HTML в Python? - PullRequest
131 голосов
/ 30 июня 2009

cgi.escape кажется одним из возможных вариантов. Это хорошо работает? Есть ли что-то, что считается лучшим?

Ответы [ 9 ]

173 голосов
/ 30 июня 2009

cgi.escape в порядке. Это ускользает:

  • < до &lt;
  • > до &gt;
  • & до &amp;

Этого достаточно для всего HTML.

РЕДАКТИРОВАТЬ: Если у вас есть не-ascii символы, которые вы также хотите экранировать, для включения в другой закодированный документ, который использует другую кодировку, например, Крейг говорит, просто используйте:

data.encode('ascii', 'xmlcharrefreplace')

Не забудьте сначала декодировать data в unicode, используя любую кодировку, в которую он был закодирован.

Однако, по моему опыту, такая кодировка бесполезна, если вы просто работаете с unicode все время от начала. Просто закодируйте в конце кодировку, указанную в заголовке документа (utf-8 для максимальной совместимости).

* +1034 * Пример: * * одна тысяча тридцать пять
>>> cgi.escape(u'<a>bá</a>').encode('ascii', 'xmlcharrefreplace')
'&lt;a&gt;b&#225;&lt;/a&gt;

Также стоит отметить (спасибо Грэгу) дополнительный параметр cgi.escape дублей. Если для него установлено значение True, cgi.escape также экранирует символы двойных кавычек ("), поэтому вы можете использовать полученное значение в атрибуте XML / HTML.

РЕДАКТИРОВАТЬ: Обратите внимание, что cgi.escape устарел в Python 3.2 в пользу html.escape, который делает то же самое, за исключением того, что quote по умолчанию равно True.

92 голосов
/ 22 февраля 2011

В Python 3.2 появился новый модуль html, который используется для экранирования зарезервированных символов из разметки HTML.

Имеет одну функцию escape():

>>> import html
>>> html.escape('x > 2 && x < 7')
'x &gt; 2 &amp;&amp; x &lt; 7'
10 голосов
/ 07 августа 2013

Если вы хотите экранировать HTML в URL:

Это, вероятно, НЕ то, что хотел ОП (вопрос не ясно указывает, в каком контексте предполагается использовать экранирование), но нативная библиотека Python urllib имеет метод экранирования сущностей HTML, необходимо безопасно включить в URL.

Ниже приведен пример:

#!/usr/bin/python
from urllib import quote

x = '+<>^&'
print quote(x) # prints '%2B%3C%3E%5E%26'

Найти документы здесь

8 голосов
/ 26 ноября 2015

Существует также превосходный markupsafe пакет .

>>> from markupsafe import Markup, escape
>>> escape("<script>alert(document.cookie);</script>")
Markup(u'&lt;script&gt;alert(document.cookie);&lt;/script&gt;')

Пакет markupsafe хорошо спроектирован и, возможно, самый универсальный и питонский способ избежать, имхо, потому что:

  1. return (Markup) является классом, производным от Unicode (т.е. isinstance(escape('str'), unicode) == True
  2. правильно обрабатывает ввод Unicode
  3. работает в Python (2.6, 2.7, 3.3 и pypy)
  4. он учитывает пользовательские методы объектов (то есть объекты со свойством __html__) и перегрузки шаблона (__html_format__).
8 голосов
/ 30 июня 2009

cgi.escape хорошо бы избегать HTML в ограниченном смысле, избегая тегов HTML и символьных сущностей.

Но вам, возможно, придется учитывать и проблемы с кодировкой: если HTML-код, который вы хотите процитировать, содержит символы, отличные от ASCII, в конкретной кодировке, вам также следует позаботиться о том, чтобы эти символы были разумно представлены при цитировании. Возможно, вы могли бы преобразовать их в сущности. В противном случае вам следует убедиться, что между исходным HTML и страницей, в которую он встроен, выполняются правильные преобразования кодировки, чтобы не повредить не-ASCII-символы.

3 голосов
/ 16 марта 2018

Нет библиотек, чистый Python, безопасно экранирует текст в HTML-текст:

text.replace('&', '&amp;').replace('>', '&gt;').replace('<', '&lt;'
        ).encode('ascii', 'xmlcharrefreplace')
2 голосов
/ 08 сентября 2015

Не самый простой способ, но все же простой. Основное отличие от модуля cgi.escape - он все равно будет работать правильно, если в вашем тексте уже есть &amp; Как видно из комментариев к нему:

cgi.escape версия

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("&", "&amp;") # Must be done first!
    s = s.replace("<", "&lt;")
    s = s.replace(">", "&gt;")
    if quote:
        s = s.replace('"', "&quot;")
    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 = {
        '<': '&gt;',
        '>': '&lt;',
        '&': '&amp;',
        '"': '&quot;', # should be escaped in attributes
        "'": '&#39'    # should be escaped in attributes
    }
    quote_pattern = re.compile(QUOTE_PATTERN)
    return re.sub(quote_pattern, lambda x: replace_with[x.group(0)], word)
2 голосов
/ 14 февраля 2015

cgi.escape расширенный

Эта версия улучшает 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'&emsp;').\
           replace(u'  ', u' &nbsp;')

например

>>> escape_html('<foo>\nfoo\t"bar"')
u'&lt;foo&gt;<br />foo&emsp;&quot;bar&quot;'
0 голосов
/ 03 марта 2015

Через BeautifulSoup4 :

>>> bs4.dammit import EntitySubstitution
>>> esub = EntitySubstitution()
>>> esub.substitute_html("r&d")
'r&amp;d'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...