113

Tôi có một chuỗi được mã hóa 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" />'''

Tôi muốn thay đổi điều đó thành:

<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" /> 

Tôi muốn đăng ký dưới dạng HTML để trình duyệt được hiển thị dưới dạng hình ảnh thay vì được hiển thị dưới dạng văn bản.

Chuỗi được lưu trữ như vậy bởi vì tôi đang sử dụng một công cụ BeautifulSoupquét web có tên , nó "quét" một trang web và nhận được một số nội dung từ nó, sau đó trả về chuỗi theo định dạng đó.

Tôi đã tìm thấy cách thực hiện điều này trong C # nhưng không phải bằng Python . Ai đó có thể giúp tôi không?

Liên quan

|
105

Với trường hợp sử dụng Django, có hai câu trả lời cho điều này. Đây là django.utils.html.escapechức năng của nó , để tham khảo:

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

Để đảo ngược điều này, hàm Cheetah được mô tả trong câu trả lời của Jake sẽ hoạt động, nhưng thiếu trích dẫn đơn. Phiên bản này bao gồm một bộ cập nhật, với thứ tự thay thế được đảo ngược để tránh các vấn đề đối xứng:

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)

Tuy nhiên, đây không phải là một giải pháp chung; nó chỉ thích hợp cho các chuỗi được mã hóa với django.utils.html.escape. Tổng quát hơn, đó là một ý tưởng tốt để gắn bó với thư viện tiêu chuẩn:

# 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)

# >= Python 3.5:
from html import unescape
unescaped = unescape(my_string)

Như một gợi ý: có thể có ý nghĩa hơn khi lưu trữ HTML không thoát khỏi cơ sở dữ liệu của bạn. Sẽ đáng để xem xét để có được kết quả không được trả lại từ BeautifulSoup nếu có thể và tránh hoàn toàn quá trình này.

Với Django, thoát chỉ xảy ra trong khi kết xuất mẫu; Vì vậy, để tránh thoát bạn chỉ cần nói với công cụ tạo khuôn mẫu không thoát khỏi chuỗi của bạn. Để làm điều đó, sử dụng một trong các tùy chọn sau trong mẫu của bạn:

{{ context_var|safe }}
{% autoescape off %}
    {{ context_var }}
{% endautoescape %}
|
  • 1

    Tại sao không sử dụng Django hoặc Cheetah?

    – Đàm Chăm 21:26:43 07/02/2009
  • 1

    Không có đối diện với django.utils.html.escape?

    – Bùi Bích Ngọc 21:38:03 07/02/2009
  • 1

    Tôi nghĩ thoát chỉ xảy ra trong Django trong quá trình kết xuất mẫu. Do đó, không cần phải có một cảnh quay - bạn chỉ cần nói với công cụ tạo khuôn mẫu không thoát ra. hoặc {{context_var | an toàn}} hoặc {% autoescape tắt%} {{context_var}} {% endautoescape%}

    – Tạ Diệp Vy 01:03:39 08/02/2009
  • 1

    @Daniel: Vui lòng thay đổi nhận xét của bạn thành câu trả lời để tôi có thể bình chọn! | an toàn là chính xác những gì tôi (và tôi chắc chắn những người khác) đang tìm kiếm để trả lời cho câu hỏi này.

    – Tạ Hoàng Thái 07:12:48 23/06/2009
  • 1

    html.parser.HTMLParser().unescape()bị phản đối trong 3,5. Sử dụng html.unescape()thay thế.

    – Lê Kim Ðan 01:11:10 30/09/2015
107

Với thư viện chuẩn:

  • Thoát 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;"))
|
  • 1

    Tôi nghĩ rằng đây là cách đơn giản nhất, 'bao gồm pin' và câu trả lời đúng. Tôi không biết tại sao mọi người bầu chọn những thứ Django / Cheetah.

    – Hoàng Tất Hiếu 13:04:31 28/03/2012
  • 1

    Tôi cũng nghĩ vậy, ngoại trừ câu trả lời này dường như không đầy đủ. HTMLParsercần phải được phân lớp, cho biết phải làm gì với tất cả các phần của bất kỳ đối tượng nào nó được cho ăn, và sau đó cho đối tượng được phân tích cú pháp, như được thấy ở đây . Ngoài ra, bạn vẫn sẽ muốn sử dụng name2codepointdict để chuyển đổi từng danh tính html thành char thực tế mà nó đại diện.

    – Dương Công Hùng 18:43:32 09/07/2012
  • 1

    Bạn đúng. Không được phân loại HTMLParserkhông thể hoạt động như chúng ta mong muốn nếu chúng ta đặt một thực thể HTML vào nó. Có lẽ tôi nên đổi tên htmlparserthành _htmlparserđể ẩn nó và chỉ hiển thị unescapephương thức giống như một hàm trợ giúp.

    – Trịnh Vĩnh Sơn 01:02:58 10/07/2012
  • 1

    Một lưu ý cho năm 2015, HTMLParser.unescape không được dùng trong py 3.4 và bị xóa trong 3.5. sử dụng from html import unescapethay thế

    – Hoàng Phương Ngọc 12:32:32 11/11/2015
  • 1

    Lưu ý rằng điều này không xử lý các ký tự đặc biệt như Umlauts của Đức ("")

    – Tạ Trúc Chi 19:11:09 15/11/2015
80

Đối với mã hóa html, có cgi.escape từ thư viện chuẩn:

>> 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.

Để giải mã html, tôi sử dụng như sau:

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)

Đối với bất cứ điều gì phức tạp hơn, tôi sử dụng BeautifulSoup.

|
20

Sử dụng giải pháp của daniel nếu tập hợp các ký tự được mã hóa tương đối hạn chế. Mặt khác, sử dụng một trong nhiều thư viện phân tích cú pháp HTML.

Tôi thích BeautifulSoup vì nó có thể xử lý XML / HTML không đúng định dạng:

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

cho câu hỏi của bạn, có một ví dụ trong tài liệu của họ

from BeautifulSoup import BeautifulStoneSoup
BeautifulStoneSoup("Sacr&eacute; bl&#101;u!", 
                   convertEntities=BeautifulStoneSoup.HTML_ENTITIES).contents[0]
# u'Sacr\xe9 bleu!'
|
9

Trong Python 3,4+:

import html

html.unescape(your_string)
|
8

Xem ở dưới cùng của trang này tại wiki Python , có ít nhất 2 tùy chọn để "unescape" html.

|
6

Nhận xét của Daniel như một câu trả lời:

"thoát chỉ xảy ra trong Django trong quá trình kết xuất mẫu. Do đó, không cần phải có một cảnh không rõ - bạn chỉ cần nói với công cụ tạo khuôn mẫu không thoát. Hoặc {{bối cảnh | % endautoescape%} "

|
5

Tôi đã tìm thấy một chức năng tốt tại: 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]
|
3

Mặc dù đây là một câu hỏi thực sự cũ, nhưng điều này có thể làm việc.

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" />'
|
  • 1

    Đây là người duy nhất có thể giải mã các cặp thay thế được mã hóa dưới dạng các thực thể html "&#55349;&#56996;". Sau đó result.encode('utf-16', 'surrogatepass').decode('utf-16'), cuối cùng tôi đã có bản gốc trở lại.

    – Lý Hải Duyên 20:04:43 06/12/2016
3

Nếu bất cứ ai đang tìm kiếm một cách đơn giản để làm điều này thông qua các mẫu django, bạn luôn có thể sử dụng các bộ lọc như thế này:

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

Tôi đã có một số dữ liệu đến từ một nhà cung cấp và mọi thứ tôi đăng đều có thẻ html thực sự được viết trên trang được hiển thị như thể bạn đang xem nguồn. Các mã trên đã giúp tôi rất nhiều. Hy vọng điều này sẽ giúp những người khác.

Chúc mừng !!

|
1

Bạn cũng có thể sử dụng django.utils.html.escape

from django.utils.html import escape

something_nice = escape(request.POST['something_naughty'])
|
1

Tôi tìm thấy điều này trong mã nguồn Cheetah ( ở đây )

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

không chắc chắn tại sao họ đảo ngược danh sách, tôi nghĩ nó phải làm theo cách họ mã hóa, vì vậy với bạn có thể không cần phải đảo ngược. Ngoài ra nếu tôi là bạn, tôi sẽ thay đổi htmlCodes thành một danh sách các bộ dữ liệu thay vì danh sách các danh sách ... điều này sẽ xuất hiện trong thư viện của tôi :)

tôi nhận thấy tiêu đề của bạn cũng được yêu cầu mã hóa, vì vậy đây là chức năng mã hóa của Cheetah.

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
|
  • 1

    Danh sách bị đảo ngược vì giải mã và thay thế mã hóa luôn phải được thực hiện đối xứng. Nếu không có sự đảo ngược, bạn có thể ví dụ. chuyển đổi '& amp; lt;' thành '& lt;', sau đó trong bước tiếp theo chuyển đổi không chính xác thành '<'.

    – Tạ Tường Hân 01:08:20 09/11/2008
0

Tìm kiếm giải pháp đơn giản nhất cho câu hỏi này trong Django và Python Tôi thấy bạn có thể sử dụng các hàm dựng sẵn của chúng để thoát / bỏ mã html.

Thí dụ

Tôi đã lưu mã html của bạn trong scraped_htmlclean_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

Bạn cần Django> = 1.0

không cảnh

Để hủy bỏ mã html bị loại bỏ của bạn, bạn có thể sử dụng django.utils.text.unescape_entities trong đó:

Chuyển đổi tất cả các tham chiếu ký tự tên và số sang các ký tự unicode tương ứng.

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

bỏ trốn

Để thoát mã html sạch của bạn, bạn có thể sử dụng django.utils.html.escape trong đó:

Trả về văn bản đã cho bằng ký hiệu, dấu ngoặc kép và dấu ngoặc nhọn được mã hóa để sử dụng trong HTML.

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

Con trăn

Bạn cần Python> = 3,4

không cảnh

Để hủy bỏ mã html bị loại bỏ của bạn, bạn có thể sử dụng html.unescape :

Chuyển đổi tất cả các tài liệu tham khảo được đặt tên và số ký tự (ví dụ &gt;, &#62;, &x3e;) trong chuỗi s cho các ký tự unicode tương ứng.

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

bỏ trốn

Để thoát mã html sạch của bạn, bạn có thể sử dụng html.escape :

Chuyển đổi các nhân vật &, <>trong chuỗi s đến chuỗi HTML-an toàn.

>>> from html import escape
>>> scraped_html == escape(clean_html)
True
|
0

Đây là giải pháp dễ nhất cho vấn đề này -

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

Từ trang này .

|
0

Dưới đây là một chức năng python sử dụng mô-đun htmlentitydefs. Nó không hoàn hảo. Phiên bản htmlentitydefsmà tôi có không đầy đủ và nó giả định rằng tất cả các thực thể giải mã thành một mật mã sai đối với các thực thể như &NotEqualTilde;:

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

NotEqualTilde;     U+02242 U+00338    ≂̸

Với những cảnh báo đó, đây là mã.

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;"
|

Câu trả lời của bạn (> 20 ký tự)

Bằng cách click "Đăng trả lời", bạn đồng ý với Điều khoản dịch vụ, Chính sách bảo mật and Chính sách cookie của chúng tôi.

Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ hoặc hỏi câu hỏi của bạn.