Frage

    

Diese Frage bereits eine Antwort hier:

    
            
  •              Decode HTML-Entitäten in Python-String?                                      5 Antworten                          
  •     
    

Ich mache ein paar Screen Scraping und Websites, HTML-Entitäten häufig nicht ASCII-Zeichen darzustellen verwenden. Ist Python hat ein Dienstprogramm, das einen String mit HTML-Entitäten nimmt und gibt einen Unicode-Typen?

Zum Beispiel:

ich zurück:

ǎ

, die eine „ǎ“ mit einem Ton Zeichen darstellt. In Binär-, wird dies als der 16-Bit-01ce dargestellt. Ich möchte die HTML-Entität in den Wert u'\u01ce' konvertieren

War es hilfreich?

Lösung

Der eigene HTMLParser Standard lib hat eine nicht dokumentierte Funktion unescape (), die genau das tut, was Sie denken, es tut:

import HTMLParser
h = HTMLParser.HTMLParser()
h.unescape('© 2010') # u'\xa9 2010'
h.unescape('© 2010') # u'\xa9 2010'

Andere Tipps

Python hat den htmlentitydefs Modul, aber das doesn‘ t enthalten eine Funktion unescape HTML-Entitäten.

Python-Entwickler Fredrik Lundh (Autor von elementtree ua) hat eine solche Funktion auf seiner Website , die mit dezimal, hex und benannten Entitäten funktionieren:

import re, htmlentitydefs

##
# Removes HTML or XML character references and entities from a text string.
#
# @param text The HTML (or XML) source text.
# @return The plain text, as a Unicode string, if necessary.

def unescape(text):
    def fixup(m):
        text = m.group(0)
        if text[:2] == "&#":
            # character reference
            try:
                if text[:3] == "&#x":
                    return unichr(int(text[3:-1], 16))
                else:
                    return unichr(int(text[2:-1]))
            except ValueError:
                pass
        else:
            # named entity
            try:
                text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
            except KeyError:
                pass
        return text # leave as is
    return re.sub("&#?\w+;", fixup, text)

Mit der eingebauten unichr - BeautifulSoup ist nicht notwendig:

>>> entity = '&#x01ce'
>>> unichr(int(entity[3:],16))
u'\u01ce'

Eine Alternative, wenn Sie lxml:

>>> import lxml.html
>>> lxml.html.fromstring('&#x01ce').text
u'\u01ce'

Wenn Sie auf Python 3.4 oder höher sind, können Sie einfach die html.unescape :

import html

s = html.unescape(s)

Sie können eine Antwort finden Sie hier - Erste internationale Zeichen von a Webseite?

Bearbeiten : Es scheint wie BeautifulSoup keine Einheiten in hexadezimal geschrieben konvertieren. Es kann festgelegt werden:

import copy, re
from BeautifulSoup import BeautifulSoup

hexentityMassage = copy.copy(BeautifulSoup.MARKUP_MASSAGE)
# replace hexadecimal character reference by decimal one
hexentityMassage += [(re.compile('&#x([^;]+);'), 
                     lambda m: '&#%d;' % int(m.group(1), 16))]

def convert(html):
    return BeautifulSoup(html,
        convertEntities=BeautifulSoup.HTML_ENTITIES,
        markupMassage=hexentityMassage).contents[0].string

html = '<html>&#x01ce;&#462;</html>'
print repr(convert(html))
# u'\u01ce\u01ce'

Bearbeiten :

unescape() Funktion von @dF die htmlentitydefs Standardmodul verwendet und unichr() könnte besser geeignet sein in diesem Fall.

Dies ist eine Funktion, die Sie soll helfen, es richtig zu machen und Einheiten konvertieren zurück in utf-8-Zeichen.

def unescape(text):
   """Removes HTML or XML character references 
      and entities from a text string.
   @param text The HTML (or XML) source text.
   @return The plain text, as a Unicode string, if necessary.
   from Fredrik Lundh
   2008-01-03: input only unicode characters string.
   http://effbot.org/zone/re-sub.htm#unescape-html
   """
   def fixup(m):
      text = m.group(0)
      if text[:2] == "&#":
         # character reference
         try:
            if text[:3] == "&#x":
               return unichr(int(text[3:-1], 16))
            else:
               return unichr(int(text[2:-1]))
         except ValueError:
            print "Value Error"
            pass
      else:
         # named entity
         # reescape the reserved characters.
         try:
            if text[1:-1] == "amp":
               text = "&amp;amp;"
            elif text[1:-1] == "gt":
               text = "&amp;gt;"
            elif text[1:-1] == "lt":
               text = "&amp;lt;"
            else:
               print text[1:-1]
               text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
         except KeyError:
            print "keyerror"
            pass
      return text # leave as is
   return re.sub("&#?\w+;", fixup, text)

Nicht sicher, warum der Stack-Überlauf-Thread umfasst nicht die ‚;‘ im Suchen / Ersetzen (dh Lambda m: '& #% d * ; *') Wenn Sie dies nicht tun, kann BeautifulSoup kotzen, weil das benachbarte Zeichen als Teil des HTML-Codes interpretiert werden kann ( dh & # 39B für & # 39Blackout).

Das funktionierte besser für mich:

import re
from BeautifulSoup import BeautifulSoup

html_string='<a href="/cgi-bin/article.cgi?f=/c/a/2010/12/13/BA3V1GQ1CI.DTL"title="">&#x27;Blackout in a can; on some shelves despite ban</a>'

hexentityMassage = [(re.compile('&#x([^;]+);'), 
lambda m: '&#%d;' % int(m.group(1), 16))]

soup = BeautifulSoup(html_string, 
convertEntities=BeautifulSoup.HTML_ENTITIES, 
markupMassage=hexentityMassage)
  1. Die int (m.group (1), 16) wandelt die Zahl (spezifiziert in der Basis 16) Format zurück auf eine ganze Zahl.
  2. m.group (0) gibt das gesamte Spiel, m.group (1) gibt die regexp Erfassungsgruppe
  3. Im Grunde genommen mit markupMessage ist das gleiche wie:
    html_string = re.sub ( '& # x ([^,] +);', lambda m: '& #% d;' % int (m.group (1), 16), html_string)

Eine andere Lösung ist die eingebaute Bibliothek xml.sax.saxutils (sowohl für HTML und XML). Allerdings wird es nur konvertieren > & amp und <.

from xml.sax.saxutils import unescape

escaped_text = unescape(text_to_escape)

Hier ist die Python 3-Version von dF Antwort :

import re
import html.entities

def unescape(text):
    """
    Removes HTML or XML character references and entities from a text string.

    :param text:    The HTML (or XML) source text.
    :return:        The plain text, as a Unicode string, if necessary.
    """
    def fixup(m):
        text = m.group(0)
        if text[:2] == "&#":
            # character reference
            try:
                if text[:3] == "&#x":
                    return chr(int(text[3:-1], 16))
                else:
                    return chr(int(text[2:-1]))
            except ValueError:
                pass
        else:
            # named entity
            try:
                text = chr(html.entities.name2codepoint[text[1:-1]])
            except KeyError:
                pass
        return text # leave as is
    return re.sub("&#?\w+;", fixup, text)

Die wichtigsten Änderungen betreffen htmlentitydefs, die jetzt html.entities und unichr, die jetzt chr ist. Sehen Sie diese Python 3 Portierungs Führung .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top