मैं पायथन / Django का उपयोग करके HTML डिकोडिंग / एन्कोडिंग कैसे कर सकता हूं?


127

मेरे पास एक स्ट्रिंग है जो 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" />'''

मैं इसे बदलना चाहता हूं:

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

मैं चाहता हूं कि यह HTML के रूप में पंजीकृत हो ताकि पाठ के रूप में प्रदर्शित होने के बजाय इसे ब्राउज़र द्वारा एक छवि के रूप में प्रस्तुत किया जाए।

स्ट्रिंग को इस तरह संग्रहीत किया जाता है क्योंकि मैं एक वेब-स्क्रैपिंग टूल का उपयोग कर रहा हूं जिसे कहा जाता है BeautifulSoup, यह वेब-पेज को "स्कैन" करता है और इससे कुछ सामग्री मिलती है, फिर उस प्रारूप में स्ट्रिंग लौटाता है।

मैंने पाया है कि यह C # में कैसे करना है, लेकिन पायथन में नहीं । क्या कोई मेरी मदद कर सकता है?

सम्बंधित

जवाबों:


118

Django उपयोग के मामले को देखते हुए, इसके दो उत्तर हैं। यहाँ इसका django.utils.html.escapeफ़ंक्शन है, संदर्भ के लिए:

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

इसे उलटने के लिए, जेक के जवाब में वर्णित चीता समारोह को काम करना चाहिए, लेकिन एकल-उद्धरण याद आ रहा है। समरूप समस्याओं से बचने के लिए प्रतिस्थापन के क्रम के साथ इस संस्करण में एक अद्यतन टपल शामिल है:

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)

यह, हालांकि, एक सामान्य समाधान नहीं है; यह केवल एन्कोड किए गए तारों के लिए उपयुक्त है django.utils.html.escape। आम तौर पर, मानक पुस्तकालय के साथ रहना एक अच्छा विचार है:

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

एक सुझाव के रूप में: यह आपके डेटाबेस में मौजूद HTML को संग्रहीत करने के लिए अधिक समझदार हो सकता है। यदि संभव हो तो सुंदरसुपे से वापस परिणाम प्राप्त करने में यह देखने लायक होगा और इस प्रक्रिया को पूरी तरह से टालना चाहिए।

Django के साथ, भागने केवल टेम्पलेट प्रतिपादन के दौरान होता है; तो बचने से बचने के लिए आप सिर्फ टेम्प्लेटिंग इंजन को कहें कि वह आपके तार से बच न जाए। ऐसा करने के लिए, अपने टेम्पलेट में इनमें से किसी एक विकल्प का उपयोग करें:

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

1
Django या चीता का उपयोग क्यों नहीं?
Mat

4
क्या django.utils.html.escape का कोई विपरीत नहीं है?
Mat

12
मुझे लगता है कि टेम्पलेट रेंडरिंग के दौरान केवल Django में बचना। इसलिए, एक यूनेस्केप की कोई आवश्यकता नहीं है - आप केवल टेंपलेटिंग इंजन को बचने के लिए नहीं कहते हैं। या तो {{reference_var | safe}} या {% autoescape ऑफ%} {{Reference_var}} {% endautoescape%}
डैनियल नाब

3
@ डैनियल: कृपया अपनी टिप्पणी को एक उत्तर में बदलें ताकि मैं उसे वोट कर सकूँ! | सुरक्षित वही था जो मैं (और मुझे यकीन है कि अन्य) इस प्रश्न के उत्तर की तलाश में था।
वेन कोर्ट्स

1
html.parser.HTMLParser().unescape()3.5 में पदावनत किया गया है। html.unescape()इसके बजाय उपयोग करें ।
pjvandehaar

114

मानक पुस्तकालय के साथ:

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

12
मुझे लगता है कि यह सबसे सीधा, 'बैटरी शामिल' और सही जवाब है। मैं नहीं जानता कि लोग उन Django / चीता वोट क्यों देते हैं।
डैनियल बख्तियार

मुझे भी ऐसा लगता है, सिवाय इसके कि यह उत्तर पूर्ण प्रतीत नहीं होता है। HTMLParserउप-वर्गित करने की आवश्यकता है, यह बताया गया है कि किसी भी वस्तु के सभी भागों के साथ क्या करना है और उसे खिलाया जाना है, जैसा कि यहां देखा गया है । इसके अलावा, आप अभी भी name2codepointप्रत्येक HTML पहचान को वास्तविक चार में बदलने के लिए तानाशाही का उपयोग करना चाहेंगे ।
मार्कोनियस

आप सही हे। HTMLParserअगर हम इसमें HTML इकाई डालते हैं, तो असंतुष्ट काम नहीं कर सकते। शायद मुझे इसे छिपाने के htmlparserलिए नाम बदलना चाहिए _htmlparser, और केवल unescapeसहायक फ़ंक्शन की तरह होने की विधि का खुलासा करना चाहिए।
जियांग जांग

3
वर्ष 2015 के लिए एक नोट, HTMLParser.unescape को py 3.4 में पदावनत किया गया और 3.5 में हटाया गया। from html import unescapeइसके बजाय का उपयोग करें
करोलिस Ryselis

2
ध्यान दें कि यह जर्मन उमलाट्स ("
576i

80

Html एन्कोडिंग के लिए, मानक पुस्तकालय से cgi.escape है:

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

Html डिकोडिंग के लिए, मैं निम्नलिखित का उपयोग करता हूं:

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)

कुछ और अधिक जटिल के लिए, मैं ब्यूटीफुल का उपयोग करता हूं।


20

डेनियल के समाधान का उपयोग करें यदि एन्कोडेड वर्णों का सेट अपेक्षाकृत प्रतिबंधित है। अन्यथा, कई HTML- पार्सिंग पुस्तकालयों में से एक का उपयोग करें।

मैं ब्यूटीफुल को पसंद करता हूं क्योंकि यह विकृत XML / HTML को हैंडल कर सकता है:

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

आपके प्रश्न के लिए, उनके प्रलेखन में एक उदाहरण है

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

; BeautifulSoup हेक्स संस्थाओं परिवर्तित नहीं करता है (& # x65) stackoverflow.com/questions/57708/...
JFS

1
ब्यूटीफुल 4 के लिए, समतुल्य होगा:from bs4 import BeautifulSoup BeautifulSoup("Sacr&eacute; bl&#101;u!").contents[0]
रेडिकैंड



6

जवाब के रूप में डैनियल की टिप्पणी:

"टेंपरेचर रेंडरिंग के दौरान केवल Django में बचना होता है। इसलिए, unescape की कोई आवश्यकता नहीं है - आप टेंपलेटिंग इंजन को बचने के लिए नहीं कहते हैं। या तो {{Reference_var | safe}} या {% autoescape off%} {{Reference_var}} { % endautoescape%} "


काम करता है, सिवाय इसके कि Django के मेरे संस्करण में 'सुरक्षित' नहीं है। मैं इसके बजाय 'एस्केप' का इस्तेमाल करता हूं। मुझे लगता है कि यह एक ही बात है।
विलेम

1
@ विल्म: वे इसके विपरीत हैं!
अशेराह

5

मुझे यहां एक अच्छा कार्य मिला: 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]

पुनः उपयोग करने का लाभ यह है कि आप दोनों को & # 039 से मिला सकते हैं; और & # 39; उसी खोज का उपयोग करना।
नील स्टब्लेन

यह प्रबंधन नहीं करती है &#xA0;जो के रूप में एक ही बात करने के लिए डिकोड करना चाहिए &#160;और &nbsp;
माइक सैमुअल

3

अगर कोई django टेम्प्लेट के माध्यम से इसे करने का एक सरल तरीका ढूंढ रहा है, तो आप हमेशा इस तरह से फ़िल्टर का उपयोग कर सकते हैं:

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

मेरे पास एक विक्रेता से आने वाला कुछ डेटा था और मैंने जो कुछ भी पोस्ट किया था उसमें HTML टैग वास्तव में दिए गए पृष्ठ पर लिखे थे जैसे कि आप स्रोत को देख रहे थे। उपरोक्त कोड ने मुझे बहुत मदद की। आशा है कि यह दूसरों की मदद करता है।

चीयर्स !!


3

हालांकि यह एक बहुत पुराना सवाल है, यह काम कर सकता है।

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
यह केवल एक है जो सरोगेट जोड़े को html संस्थाओं के रूप में एन्कोडेड जोड़े को डीकोड करने में सक्षम था "&#55349;&#56996;"। फिर एक के बाद result.encode('utf-16', 'surrogatepass').decode('utf-16'), मैं अंत में मूल वापस आ गया था।
बचाया

1

मुझे यह चीता स्रोत कोड ( यहां ) में मिला

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

निश्चित नहीं है कि वे सूची को उल्टा क्यों करते हैं, मुझे लगता है कि इसका उस तरह से करना है जो वे एनकोड करते हैं, इसलिए आपके साथ इसे उलटने की आवश्यकता नहीं है। इसके अलावा, अगर मैं आप होता तो मैं htmlCodes को सूचियों की सूची के बजाय ट्यूपल्स की सूची में बदल देता ... यह मेरी लाइब्रेरी में चल रहा है, हालांकि :)

मैंने देखा कि आपके शीर्षक ने एनकोड के लिए भी कहा है, इसलिए यहां चीता का एनकोड फ़ंक्शन है।

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

2
सूची को उलट दिया गया है क्योंकि डिकोड और एनकोड प्रतिस्थापन को हमेशा सममित रूप से बनाया जाना है। उलट के बिना आप उदा सकता है। कन्वर्ट '& lt;' '& lt;' पर, फिर अगले चरण में गलत तरीके से इसे '<' में बदलें।
1

1

आप django.utils.html.escape का भी उपयोग कर सकते हैं

from django.utils.html import escape

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

ओपी ने बचने के बारे में पूछा, बचने के लिए नहीं।
क्लेमासन

इसके शीर्षक में उन्होंने एन्कोडिंग के लिए भी कहा - बस आपका जवाब मिल गया और मैं इसके लिए आभारी हूं।
साइमन स्टीनबर्गर

1
ओपी ने जो नहीं पूछा, लेकिन मुझे यह उपयोगी लगा।
रेक्टैंग्लेंगल

0

नीचे एक पायथन फ़ंक्शन है जो मॉड्यूल का उपयोग करता है htmlentitydefs। यह सही नहीं है। htmlentitydefsमेरे पास जो संस्करण है वह अधूरा है और यह मानता है कि सभी इकाइयां एक कोडपॉइंट को डिकोड करती हैं जो कि संस्थाओं के लिए गलत है &NotEqualTilde;:

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

NotEqualTilde;     U+02242 U+00338    ≂̸

हालांकि उन कैविटीज़ के साथ, यहाँ कोड है।

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


0

Django और पायथन में इस सवाल का सबसे सरल समाधान खोज मैंने पाया कि आप HTML कोड से बचने / अनस्कैप करने के लिए बिल्टिन कार्यों का उपयोग कर सकते हैं।

उदाहरण

मैं में अपने html कोड बचाया scraped_htmlऔर 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

आपको Django> = 1.0 की आवश्यकता है

unescape

अपने स्क्रैप किए गए html कोड को अनसैप करने के लिए आप django.utils.text.unescape_entities का उपयोग कर सकते हैं :

सभी नामांकित और संख्यात्मक वर्ण संदर्भों को संबंधित यूनिकोड वर्णों में बदलें।

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

पलायन

अपने स्वच्छ html कोड से बचने के लिए आप django.utils.html.escape का उपयोग कर सकते हैं :

HTML में उपयोग के लिए एन्कोड किए गए ampersands, उद्धरण और कोण कोष्ठक के साथ दिए गए पाठ को वापस करता है।

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

अजगर

आपको पाइथन> = 3.4 चाहिए

unescape

अपने स्क्रैप किए गए HTML कोड को अनसेक करने के लिए आप html.unescape का उपयोग कर सकते हैं :

सभी नामित और आंकिक केरेक्टर सन्दर्भ (जैसे कन्वर्ट &gt;, &#62;, &x3e;इसी यूनिकोड वर्ण के लिए स्ट्रिंग में)।

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

पलायन

अपने स्वच्छ HTML कोड से बचने के लिए आप html.escape का उपयोग कर सकते हैं :

वर्णों को परिवर्तित करें &, <और >स्ट्रिंग-से HTML- सुरक्षित अनुक्रम में।

>>> from html import escape
>>> scraped_html == escape(clean_html)
True
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.