18

Estoy intentando decodificar las entradas HTML desde aquí NYTimes.com y no puedo entender lo que estoy haciendo mal.Decodificación de entidades HTML con Python

Tomemos, por ejemplo:

"U.S. Adviser’s Blunt Memo on Iraq: Time ‘to Go Home’" 

He intentado BeautifulSoup, decodificar ('iso-8859-1'), y smart_str de django.utils.encoding sin ningún éxito.

+0

Esta pregunta parece surgir mucho sin una buena solución. Me da ganas de escribir algo mío ... – Triptych

+0

Ha Creo que es la mejor solución que he encontrado hasta ahora. De hecho, podría intentar hacer eso yo mismo. Si lo hago, publicaré mi solución. – KeyboardInterrupt

+0

@Triptych: there is ['unescape()'] (http://stackoverflow.com/a/20715131/4279). – jfs

Respuesta

6

Prueba esto:

import re 

def _callback(matches): 
    id = matches.group(1) 
    try: 
     return unichr(int(id)) 
    except: 
     return id 

def decode_unicode_references(data): 
    return re.sub("&#(\d+)(;|(?=\s))", _callback, data) 

data = "U.S. Adviser’s Blunt Memo on Iraq: Time ‘to Go Home’" 
print decode_unicode_references(data) 
+0

UnicodeEncodeError: el códec "charmap" no puede codificar el carácter u '\ u2019' en la posición 12: mapas de caracteres a Este parece ser el error que sigo recibiendo independientemente de lo que intento. – KeyboardInterrupt

+0

¿Podría proporcionar más código, entonces? Lo probé con la función que escribí y el personaje 2019 funciona bien. Se muestra como: ߣ –

+0

Algunas preguntas sobre su expresión regular: (1) ¿No debería ser \ d en lugar de \ w? La expresión regular coincidirá con ' ' y ' ' pero luego se bloqueará en int() (2) Permitir que la referencia de caracteres (NO sea una entidad) termine en un espacio en blanco en lugar de ';' parece muy tolerante, ¿no deberías mencionar esto? (3) ¿No sería mejor escribir la última parte como [; \ s]? –

18

Esto funciona:

from BeautifulSoup import BeautifulStoneSoup 
s = "U.S. Adviser’s Blunt Memo on Iraq: Time ‘to Go Home’" 
decoded = BeautifulStoneSoup(s, convertEntities=BeautifulStoneSoup.HTML_ENTITIES) 

Si quieres una cadena en lugar de un objeto Unicode, que necesitará para decodificarlo a una codificación que los soportes los personajes que se usan; ISO-8859-1 no:

result = decoded.encode("UTF-8") 

Es lamentable que necesite un módulo externo para algo como esto; la decodificación sencilla de las entidades HTML/XML debe estar en la biblioteca estándar, y no requerir que utilice una biblioteca con nombres de clases sin sentido como "BeautifulStoneSoup". (Los nombres de clases y funciones no deben ser "creativos", deben ser significativos.)

+2

lxml, por desgracia, no en la biblioteca estándar, también proporciona un analizador de Beautiful Soup (y mucho más) con nombres algo menos "creativos". –

+1

El soporte para la descodificación de entidades se encuentra en la biblioteca estándar (módulo htmlentitydefs). Lo que OP tiene son referencias de caracteres numéricos (decimales), no entidades. –

+0

Funciona también con BeautifulSoup en lugar de BeautifulStoneSoup: un paso menos "creativo" :) –

20

En realidad, lo que tiene no son entidades HTML. Hay TRES variedades de esos & .....; thingies - por ejemplo       all mean U + 00A0 NO-BREAK SPACE.

  (el tipo que tiene) es una "referencia de caracteres numéricos" (decimal).
  es una "referencia de caracteres numéricos" (hexadecimal).
  es una entidad.

Más información: http://htmlhelp.com/reference/html40/entities/

Aquí encontrará código para python2.X que hace las tres cosas en una exploración a través de la entrada: http://effbot.org/zone/re-sub.htm#unescape-html

+0

+1 para el enlace effbot.org, ¡muy valioso! –

16
>>> from HTMLParser import HTMLParser 
>>> print HTMLParser().unescape('U.S. Adviser’s Blunt Memo on Iraq: ' 
...        'Time ‘to Go Home’') 
U.S. Adviser’s Blunt Memo on Iraq: Time ‘to Go Home’ 

La función no está documentada en Python 2. It is fixed in Python 3.4+: está expuesto como html.unescape() there.

+4

Para usuarios futuros, esta respuesta parece tener tan pocos votos positivos simplemente porque llegó 4 años más tarde que las respuestas existentes. Parece ser al menos una buena respuesta. Esta respuesta tiene la ventaja de que es simple (a diferencia de escribir su propia función para interpretar estándares HTML utilizando una expresión regular) y utiliza una biblioteca estándar (a diferencia de BeautifulSoup). Tiene la desventaja de que es el uso de una función no documentada. –

+0

¡Vota esta gente! – Private

Cuestiones relacionadas