2009-03-31 9 views
47

doublons possibles:Convertir les entités HTML à Unicode et vice versa

Comment convertir les entités HTML Unicode et vice versa en Python ?

+16

@Jarret Hardie: en fait, show-and-tell est parfaitement bien sur le SO. De la première entrée sur la FAQ (http://stackoverflow.com/faq) "Il est également parfaitement possible de poser et de répondre à votre propre question de programmation". Bien que, il est également encouragé à rechercher des doublons aussi bien. – chauncey

+12

Je poste des questions auxquelles j'ai répondu par le passé au profit d'autres utilisateurs cherchant des réponses similaires. – hekevintran

+6

+1 Il contribue à l'ensemble de données. –

Répondre

22

Vous devez avoir BeautifulSoup.

from BeautifulSoup import BeautifulStoneSoup 
import cgi 

def HTMLEntitiesToUnicode(text): 
    """Converts HTML entities to unicode. For example '&' becomes '&'.""" 
    text = unicode(BeautifulStoneSoup(text, convertEntities=BeautifulStoneSoup.ALL_ENTITIES)) 
    return text 

def unicodeToHTMLEntities(text): 
    """Converts unicode to HTML entities. For example '&' becomes '&'.""" 
    text = cgi.escape(text).encode('ascii', 'xmlcharrefreplace') 
    return text 

text = "&, ®, <, >, ¢, £, ¥, €, §, ©" 

uni = HTMLEntitiesToUnicode(text) 
htmlent = unicodeToHTMLEntities(uni) 

print uni 
print htmlent 
# &, ®, <, >, ¢, £, ¥, €, §, © 
# &amp;, &#174;, &lt;, &gt;, &#162;, &#163;, &#165;, &#8364;, &#167;, &#169; 
+1

L'API de BeautifulSoup a changé. S'il vous plaît voir le plus récent [doc] (http://www.crummy.com/software/BeautifulSoup/bs4/doc/). – bahmait

+0

@hekevintran: Est-il possible d'imprimer '& # x00A2 ;, & # x00A3 ;, & # x00A5 ;, & # x20AC ;, & # x00A7 ;, & # x00A9;' au lieu de '¢, £, ¥, €, §, ©'. Une idée? – Jagath

78

Quant au "vice versa" (que je me devais, me conduisant à trouver cette question, qui n'a pas aidé, et par la suite another site which had the answer):

u'some string'.encode('ascii', 'xmlcharrefreplace') 

retournera une chaîne de caractères avec des caractères non-ascii transformés en entités XML (HTML).

+1

J'ai oublié xmlcharrefreplace et c'était très utile. Chaque fois que je dois stocker en toute sécurité des caractères codés ou non-ascii dans mysql, je trouve que j'ai besoin d'utiliser cette méthode. – cybertoast

+1

Cela ne fonctionne pas avec un littéral de chaîne contenant le caractère unicode U + 2019 équivalent entité HTML ’ N'est-ce pas ce que la question demandait (cette réponse convertit ascii qui est un sous-ensemble d'unicode)? text.decode ('utf-8'). Encoder ('ascii', 'xmlcharrefreplace') –

+1

@MikeS Cela fonctionne sans problème; '>>>' u '\ u2019'.encode (' utf-8 '). decode (' utf-8 '). encoder (' ascii ',' xmlcharrefreplace ') 'donne'' ’ '' –

4

Comme hekevintran réponse suggère, vous pouvez utiliser cgi.escape(s) pour le codage des piqûres, mais remarquez que le codage de la citation est fausse par défaut dans cette fonction et il peut être une bonne idée de passer l'argument de mot-clé quote=True à côté de votre chaîne. Mais même en passant quote=True, la fonction ne sera pas échapper à des guillemets simples ("'") (En raison de ces problèmes, la fonction a été deprecated depuis la version 3.2)

Il a été suggéré d'utiliser html.escape(s) au lieu de cgi.escape(s). (Nouveau dans la version 3.2)

Egalement html.unescape(s) a été introduced in version 3.4.

Donc, en python 3.4, vous pouvez:

  • Utilisez html.escape(text).encode('ascii', 'xmlcharrefreplace').decode() pour convertir des caractères spéciaux en entités HTML.
  • et html.unescape(text) pour la conversion des entités HTML en représentations de texte brut.
+1

En Python 2.7 vous peut utiliser HTMLParser.unescape (texte) – frank

12

Mise à jour pour Python 2.7 et BeautifulSoup4

Unescape - Unicode HTML unicode avec htmlparser (Python 2.7 lib standard):

>>> escaped = u'Monsieur le Cur&eacute; of the &laquo;Notre-Dame-de-Gr&acirc;ce&raquo; neighborhood' 
>>> from HTMLParser import HTMLParser 
>>> htmlparser = HTMLParser() 
>>> unescaped = htmlparser.unescape(escaped) 
>>> unescaped 
u'Monsieur le Cur\xe9 of the \xabNotre-Dame-de-Gr\xe2ce\xbb neighborhood' 
>>> print unescaped 
Monsieur le Curé of the «Notre-Dame-de-Grâce» neighborhood 

Unescape - Unicode HTML en Unicode avec bs4 (BeautifulSoup4):

>>> html = '''<p>Monsieur le Cur&eacute; of the &laquo;Notre-Dame-de-Gr&acirc;ce&raquo; neighborhood</p>''' 
>>> from bs4 import BeautifulSoup 
>>> soup = BeautifulSoup(html) 
>>> soup.text 
u'Monsieur le Cur\xe9 of the \xabNotre-Dame-de-Gr\xe2ce\xbb neighborhood' 
>>> print soup.text 
Monsieur le Curé of the «Notre-Dame-de-Grâce» neighborhood 

Escape - Unicode en Unicode HTML avec bs4 (BeautifulSoup4):

>>> unescaped = u'Monsieur le Curé of the «Notre-Dame-de-Grâce» neighborhood' 
>>> from bs4.dammit import EntitySubstitution 
>>> escaper = EntitySubstitution() 
>>> escaped = escaper.substitute_html(unescaped) 
>>> escaped 
u'Monsieur le Cur&eacute; of the &laquo;Notre-Dame-de-Gr&acirc;ce&raquo; neighborhood' 
+0

upvote pour montrer une solution de bibliothèque standard sans dépendances –

+0

Revisiting Je viens de voir le commentaire @bobince à gauche sur la question pointant vers [cette réponse] (http://stackoverflow.com/a/663128/1599229). Puisque 'htmlparser' est documenté maintenant, et que ce commentaire n'est pas important, il laisse cette partie de réponse. – bahmait

0

J'ai utilisé la fonction suivante pour convertir unicode extrait d'un fichier xls en un fichier html tout en conservant les caractères spéciaux trouvés dans le fichier xls:

def html_wr(f, dat): 
    ''' write dat to file f as html 
     . file is assumed to be opened in binary format 
     . if dat is nul it is replaced with non breakable space 
     . non-ascii characters are translated to xml  
    ''' 
    if not dat: 
     dat = '&nbsp;' 
    try: 
     f.write(dat.encode('ascii')) 
    except: 
     f.write(html.escape(dat).encode('ascii', 'xmlcharrefreplace')) 

Espérons que cela est utile à quelqu'un

0

Si quelqu'un comme moi est là-bas se demander pourquoi certains numéros d'entité (codes) comme &#153; (for trademark symbol), &#128; (for euro symbol) ne sont pas codés correctement, la raison est dans la norme ISO-8859-1 (alias Windows-1252) ces caractères ne sont pas définis.

Notez également que, le caractère par défaut défini au html5 est utf-8 était ISO-8859-1 pour html4

Ainsi, nous devrons contourner en quelque sorte (trouver & remplacer ceux au premier)

référence (point de départ) de la documentation de Mozilla

https://developer.mozilla.org/en-US/docs/Web/Guide/Localizations_and_character_encodings

Questions connexes