Como faço para executar HTML decodificação / codificação usando Python / Django?

votos
107

Eu tenho uma seqüência que é html codificado:

<img class="size-medium wp-image-113" 
  style="margin-left: 15px;" title="su1" 
  src="http://blah.org/wp-content/uploads/2008/10/su1-300x194.jpg" 
  alt="" width="300" height="194" />

Eu quero mudar isso para:

<img class=size-medium wp-image-113 style=margin-left: 15px; 
  title=su1 src=http://blah.org/wp-content/uploads/2008/10/su1-300x194.jpg 
  alt= width=300 height=194 /> 

Eu quero que isso se registrar como HTML para que ele seja processado como uma imagem pelo navegador em vez de ser exibido como texto.

Eu descobri como fazer isso em C #, mas não em em Python. Alguém pode me ajudar?

Obrigado.

Edit: Alguém perguntou por que minhas cordas estão armazenados assim. É porque eu estou usando uma ferramenta de web scraping que scans uma página da web e recebe um determinado conteúdo a partir dele. A ferramenta (BeautifulSoup) retorna a string nesse formato.

relacionado

Publicado 08/11/2008 em 21:44
fonte usuário
Em outras línguas...                            


15 respostas

votos
102

Dado o caso de uso Django, há duas respostas para isso. Aqui é a sua django.utils.html.escapefunção, para referência:

def escape(html):
    """Returns the given HTML with ampersands, quotes and carets encoded."""
    return mark_safe(force_unicode(html).replace('&', '&amp;').replace('<', '&l
t;').replace('>', '&gt;').replace('"', '&quot;').replace("'", '&#39;'))

Para inverter esta situação, a função Cheetah descrito na resposta de Jake deve funcionar, mas está faltando a aspa simples. Esta versão inclui uma tupla atualizadas, com a ordem de substituição invertido para evitar problemas simétricos:

def html_decode(s):
    """
    Returns the ASCII decoded version of the given HTML string. This does
    NOT remove normal HTML tags like <p>.
    """
    htmlCodes = (
            ("'", '&#39;'),
            ('"', '&quot;'),
            ('>', '&gt;'),
            ('<', '&lt;'),
            ('&', '&amp;')
        )
    for code in htmlCodes:
        s = s.replace(code[1], code[0])
    return s

unescaped = html_decode(my_string)

Isto, no entanto, não é uma solução geral; é apropriado apenas para cordas codificados com django.utils.html.escape. De modo mais geral, é uma boa idéia para ficar com a biblioteca padrão:

# Python 2.x:
import HTMLParser
html_parser = HTMLParser.HTMLParser()
unescaped = html_parser.unescape(my_string)

# Python 3.x:
import html.parser
html_parser = html.parser.HTMLParser()
unescaped = html_parser.unescape(my_string)

Como sugestão: pode fazer mais sentido para armazenar o unescaped HTML em seu banco de dados. Seria pena olhar para a obtenção de resultados unescaped volta de BeautifulSoup se possível, e evitar este processo como um todo.

Com Django, escapando só ocorre durante a renderização de templates; de modo a evitar escapar você acabou de dizer ao motor de templates para não escapar de sua corda. Para fazer isso, use uma destas opções em seu modelo:

{{ context_var|safe }}
{% autoescape off %}
    ` context_var `
{% endautoescape %}
Respondeu 08/11/2008 em 22:40
fonte usuário

votos
96

Com a biblioteca padrão:

  • Fuga HTML

    try:
        from html import escape  # python 3.x
    except ImportError:
        from cgi import escape  # python 2.x
    
    print(escape("<"))
    
  • HTML Unescape

    try:
        from html import unescape  # python 3.4+
    except ImportError:
        try:
            from html.parser import HTMLParser  # python 3.x (<3.4)
        except ImportError:
            from HTMLParser import HTMLParser  # python 2.x
        unescape = HTMLParser().unescape
    
    print(unescape("&gt;"))
    
Respondeu 17/08/2011 em 06:51
fonte usuário

votos
79

Para codificação html, há cgi.escape da biblioteca padrão:

>> help(cgi.escape)
cgi.escape = 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.

Para html decodificação, eu uso o seguinte:

import re
from htmlentitydefs import name2codepoint
# for some reason, python 2.5.2 doesn't have this one (apostrophe)
name2codepoint['#39'] = 39

def unescape(s):
    "unescape HTML code refs; c.f. http://wiki.python.org/moin/EscapingHtml"
    return re.sub('&(%s);' % '|'.join(name2codepoint),
              lambda m: unichr(name2codepoint[m.group(1)]), s)

Para algo mais complicado, eu uso BeautifulSoup.

Respondeu 16/01/2009 em 02:12
fonte usuário

votos
20

Use solução de Daniel se o conjunto de caracteres codificados é relativamente restrito. Caso contrário, use uma das inúmeras bibliotecas de análise de HTML.

Eu gosto BeautifulSoup porque ele pode lidar mal formado XML / HTML:

http://www.crummy.com/software/BeautifulSoup/

para sua pergunta, há um exemplo em sua documentação

from BeautifulSoup import BeautifulStoneSoup
BeautifulStoneSoup("Sacr&eacute; bl&#101;u!", 
                   convertEntities=BeautifulStoneSoup.HTML_ENTITIES).contents[0]
# u'Sacr\xe9 bleu!'
Respondeu 09/11/2008 em 02:15
fonte usuário

votos
8

Em Python 3.4+:

import html

html.unescape(your_string)
Respondeu 08/07/2015 em 01:54
fonte usuário

votos
8

Veja na parte inferior desta página em Python wiki , há pelo menos 2 opções para HTML "unescape".

Respondeu 23/11/2008 em 14:50
fonte usuário

votos
6

O comentário de Daniel como uma resposta:

. "Escapar só ocorre em Django durante renderização modelo Portanto, não há necessidade de um unescape - basta dizer ao motor de templates para não fugir tanto {{context_var | segura}}. Ou {% autoescape off%}` context_var `{% endautoescape %}"

Respondeu 24/10/2009 em 23:04
fonte usuário

votos
5

Eu encontrei uma função bem em: http://snippets.dzone.com/posts/show/4569

def decodeHtmlentities(string):
    import re
    entity_re = re.compile("&(#?)(\d{1,5}|\w{1,8});")

    def substitute_entity(match):
        from htmlentitydefs import name2codepoint as n2cp
        ent = match.group(2)
        if match.group(1) == "#":
            return unichr(int(ent))
        else:
            cp = n2cp.get(ent)

            if cp:
                return unichr(cp)
            else:
                return match.group()

    return entity_re.subn(substitute_entity, string)[0]
Respondeu 17/07/2010 em 14:27
fonte usuário

votos
3

Mesmo que esta é uma pergunta muito antiga, isso pode funcionar.

Django 1.5.5

In [1]: from django.utils.text import unescape_entities
In [2]: unescape_entities('&lt;img class=&quot;size-medium wp-image-113&quot; style=&quot;margin-left: 15px;&quot; title=&quot;su1&quot; src=&quot;http://blah.org/wp-content/uploads/2008/10/su1-300x194.jpg&quot; alt=&quot;&quot; width=&quot;300&quot; height=&quot;194&quot; /&gt;')
Out[2]: u'<img class="size-medium wp-image-113" style="margin-left: 15px;" title="su1" src="http://blah.org/wp-content/uploads/2008/10/su1-300x194.jpg" alt="" width="300" height="194" />'
Respondeu 01/02/2015 em 21:31
fonte usuário

votos
3

Se alguém está procurando uma maneira simples de fazer isso através dos modelos de Django, você sempre pode usar filtros como este:

<html>
{{ node.description|safe }}
</html>

Eu tive alguns dados provenientes de um fornecedor e tudo que eu postei teve tags HTML realmente escrito na página processado como se você estivesse olhando para a fonte. O código acima me ajudou muito. Espero que isso ajude os outros.

Felicidades!!

Respondeu 21/12/2011 em 18:08
fonte usuário

votos
1

Você também pode usar django.utils.html.escape

from django.utils.html import escape

something_nice = escape(request.POST['something_naughty'])
Respondeu 27/02/2012 em 17:01
fonte usuário

votos
1

Achei isso no código fonte Cheetah ( aqui )

htmlCodes = [
    ['&', '&amp;'],
    ['<', '&lt;'],
    ['>', '&gt;'],
    ['"', '&quot;'],
]
htmlCodesReversed = htmlCodes[:]
htmlCodesReversed.reverse()
def htmlDecode(s, codes=htmlCodesReversed):
    """ Returns the ASCII decoded version of the given HTML string. This does
        NOT remove normal HTML tags like <p>. It is the inverse of htmlEncode()."""
    for code in codes:
        s = s.replace(code[1], code[0])
    return s

não tenho certeza por isso que eles reverter a lista, eu acho que tem a ver com a forma como eles codificam, assim com você não pode precisar de ser revertida. Além disso, se eu fosse você eu iria mudar htmlCodes para ser uma lista de tuplas em vez de uma lista de listas ... isso vai na minha biblioteca embora :)

eu notei seu título pediu para codificar também, então aqui é a função de codificação de Chita.

def htmlEncode(s, codes=htmlCodes):
    """ Returns the HTML encoded version of the given string. This is useful to
        display a plain ASCII text string on a web page."""
    for code in codes:
        s = s.replace(code[0], code[1])
    return s
Respondeu 08/11/2008 em 21:58
fonte usuário

votos
0

Buscando a solução mais simples desta questão no Django e Python Eu achei que você pode usar funções DELE embutidas para escapar / código html unescape.

Exemplo

Salvei o código html em scraped_htmle clean_html:

scraped_html = (
    '&lt;img class=&quot;size-medium wp-image-113&quot; '
    'style=&quot;margin-left: 15px;&quot; title=&quot;su1&quot; '
    'src=&quot;http://blah.org/wp-content/uploads/2008/10/su1-300x194.jpg&quot; '
    'alt=&quot;&quot; width=&quot;300&quot; height=&quot;194&quot; /&gt;'
)
clean_html = (
    '<img class="size-medium wp-image-113" style="margin-left: 15px;" '
    'title="su1" src="http://blah.org/wp-content/uploads/2008/10/su1-300x194.jpg" '
    'alt="" width="300" height="194" />'
)

Django

Você precisa Django> = 1,0

unescape

Para unescape seu código html raspados você pode usar django.utils.text.unescape_entities que:

Converter todas as referências personagem chamado e numéricas para os caracteres Unicode correspondentes.

>>> from django.utils.text import unescape_entities
>>> clean_html == unescape_entities(scraped_html)
True

escapar

Para escapar seu código html limpo você pode usar django.utils.html.escape que:

Retorna o texto dado com ampersands, citações e colchetes codificados para uso em HTML.

>>> from django.utils.html import escape
>>> scraped_html == escape(clean_html)
True

píton

Você precisa Python> = 3,4

unescape

Para unescape seu código html raspados você pode usar html.unescape que:

Converter todas as referências nomeadas e numérico de caracteres (por exemplo &gt;, &#62;, &x3e;) na cadeia de s para os caracteres Unicode correspondentes.

>>> from html import unescape
>>> clean_html == unescape(scraped_html)
True

escapar

Para escapar seu código html limpo você pode usar html.escape que:

Converter os caracteres &, <e >na string s para seqüências HTML-seguras.

>>> from html import escape
>>> scraped_html == escape(clean_html)
True
Respondeu 18/07/2018 em 14:13
fonte usuário

votos
0

Esta é a solução mais fácil para este problema -

{% autoescape on %}
   ` body `
{% endautoescape %}

A partir desta página .

Respondeu 30/06/2012 em 10:56
fonte usuário

votos
0

Abaixo está uma função de python que usa módulo htmlentitydefs. Ele não é perfeito. A versão htmlentitydefsque eu tenho é incompleta e ele assume que todas as entidades decodificar a um codepoint que é errado para entidades como &NotEqualTilde;:

http://www.w3.org/TR/html5/named-character-references.html

NotEqualTilde;     U+02242 U+00338    ≂̸

Com essas ressalvas, porém, aqui está o código.

def decodeHtmlText(html):
    """
    Given a string of HTML that would parse to a single text node,
    return the text value of that node.
    """
    # Fast path for common case.
    if html.find("&") < 0: return html
    return re.sub(
        '&(?:#(?:x([0-9A-Fa-f]+)|([0-9]+))|([a-zA-Z0-9]+));',
        _decode_html_entity,
        html)

def _decode_html_entity(match):
    """
    Regex replacer that expects hex digits in group 1, or
    decimal digits in group 2, or a named entity in group 3.
    """
    hex_digits = match.group(1)  # '&#10;' -> unichr(10)
    if hex_digits: return unichr(int(hex_digits, 16))
    decimal_digits = match.group(2)  # '&#x10;' -> unichr(0x10)
    if decimal_digits: return unichr(int(decimal_digits, 10))
    name = match.group(3)  # name is 'lt' when '&lt;' was matched.
    if name:
        decoding = (htmlentitydefs.name2codepoint.get(name)
            # Treat &GT; like &gt;.
            # This is wrong for &Gt; and &Lt; which HTML5 adopted from MathML.
            # If htmlentitydefs included mappings for those entities,
            # then this code will magically work.
            or htmlentitydefs.name2codepoint.get(name.lower()))
        if decoding is not None: return unichr(decoding)
    return match.group(0)  # Treat "&noSuchEntity;" as "&noSuchEntity;"
Respondeu 15/12/2011 em 19:01
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more