web-dev-qa-db-ja.com

PythonでHTMLをエスケープする最も簡単な方法は何ですか?

cgi.escapeは選択肢の1つに思えます。それはうまく機能しますか?より良いと考えられるものはありますか?

131
Josh Gibson

cgi.escape で問題ありません。逃げる:

  • <から&lt;
  • >から&gt;
  • &から&amp;

これですべてのHTMLで十分です。

編集:非ASCII文字を持っている場合は、Craigのような異なるエンコーディングを使用する別のエンコードされたドキュメントに含めるために、エスケープしたいつかいます:

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

エンコードされたエンコードを使用して、最初にdataunicodeにデコードすることを忘れないでください。

しかし、私の経験では、unicodeを最初からずっと使用しているだけでは、この種のエンコーディングは役に立ちません。最後に、ドキュメントヘッダーで指定されたエンコードにエンコードします(互換性を最大限にするには、utf-8)。

例:

>>> cgi.escape(u'<a>bá</a>').encode('ascii', 'xmlcharrefreplace')
'&lt;a&gt;b&#225;&lt;/a&gt;

また、Gregに感謝します。余分なquoteパラメーターcgi.escapeが必要です。 Trueに設定すると、cgi.escapeは二重引用符文字(")もエスケープするため、結果の値をXML/HTML属性で使用できます。

編集:cgi.escapeはPython 3.2で非推奨になり、 html.escape が推奨されますが、quoteデフォルトはTrueです。

174
nosklo

Python 3.2では、新しい html モジュールが導入されました。これは、HTMLマークアップから予約文字をエスケープするために使用されます。

関数escape()が1つあります:

>>> import html
>>> html.escape('x > 2 && x < 7')
'x &gt; 2 &amp;&amp; x &lt; 7'
93
Maciej Ziarko

URLでHTMLをエスケープしたい場合:

これはおそらくOPが望んだものではありません(質問はどのコンテキストでエスケープが使用されることを明確に示していない)が、Pythonのネイティブライブラリ rllib には必要なHTMLエンティティをエスケープする方法がありますURLに安全に含めてください。

次に例を示します。

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

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

ここでドキュメントを検索

10
SuperFamousGuy

優れた markupsafeパッケージ もあります。

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

markupsafeパッケージは適切に設計されており、おそらく最も汎用的でPython的な方法でエスケープを実行します。

  1. 戻り値(Markup)は、Unicodeから派生したクラスです(つまり、isinstance(escape('str'), unicode) == True
  2. ユニコード入力を適切に処理します
  3. Python(2.6、2.7、3.3、およびpypy)で動作します
  4. オブジェクトのカスタムメソッド(つまり、__html__プロパティを持つオブジェクト)およびテンプレートのオーバーロード(__html_format__)を尊重します。
8
Brian M. Hunt

cgi.escape は、HTMLタグと文字エンティティをエスケープするという限られた意味でHTMLをエスケープするのに適しているはずです。

ただし、エンコードの問題も考慮する必要があります。引用するHTMLに特定のエンコードで非ASCII文字が含まれている場合、引用時にそれらを適切に表現するように注意する必要があります。おそらく、それらをエンティティに変換できます。それ以外の場合は、非ASCII文字の破損を避けるために、「ソース」HTMLとそれが埋め込まれているページの間で正しいエンコード変換が行われることを確認する必要があります。

8
Craig McQueen

純粋なPythonのライブラリは、テキストをHTMLテキストに安全にエスケープしません。

text.replace('&', '&amp;').replace('>', '&gt;').replace('<', '&lt;'
        ).encode('ascii', 'xmlcharrefreplace')
3
speedplane

最も簡単な方法ではありませんが、それでも簡単です。 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
palestamp

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;'
2

BeautifulSoup4 経由:

>>> bs4.dammit import EntitySubstitution
>>> esub = EntitySubstitution()
>>> esub.substitute_html("r&d")
'r&amp;d'
0
scharfmn