¿Cómo analizar correctamente HTML codificado en UTF-8 a cadenas Unicode con BeautifulSoup?

Estoy ejecutando un progtwig Python que recupera una página web codificada en UTF-8, y extraigo un texto del HTML usando BeautifulSoup.

Sin embargo, cuando escribo este texto en un archivo (o lo imprimo en la consola), se escribe en una encoding inesperada.

Progtwig de muestra:

import urllib2 from BeautifulSoup import BeautifulSoup # Fetch URL url = 'http://www.voxnow.de/' request = urllib2.Request(url) request.add_header('Accept-Encoding', 'utf-8') # Response has UTF-8 charset header, # and HTML body which is UTF-8 encoded response = urllib2.urlopen(request) # Parse with BeautifulSoup soup = BeautifulSoup(response) # Print title attribute of a 
which uses umlauts (eg können) print repr(soup.find('div', id='navbutton_account')['title'])

Ejecutando esto da el resultado:

 # u'Hier k\u0102\u015bnnen Sie sich kostenlos registrieren und / oder einloggen!' 

Pero esperaría que una cadena Python Unicode se representara ö en la palabra können como \xf6 :

 # u'Hier k\xf6bnnen Sie sich kostenlos registrieren und / oder einloggen!' 

He intentado pasar el parámetro ‘fromEncoding’ a BeautifulSoup, y he intentado read() y decode() el objeto de response , pero o bien no hace ninguna diferencia o produce un error.

Con el comando curl www.voxnow.de | hexdump -C curl www.voxnow.de | hexdump -C , puedo ver que la página web está de hecho codificada en UTF-8 (es decir, contiene 0xc3 0xb6 ) para el carácter ö :

  20 74 69 74 6c 65 3d 22 48 69 65 72 20 6b c3 b6 | title="Hier k..| 6e 6e 65 6e 20 53 69 65 20 73 69 63 68 20 6b 6f |nnen Sie sich ko| 73 74 65 6e 6c 6f 73 20 72 65 67 69 73 74 72 69 |stenlos registri| 

Estoy más allá del límite de mis habilidades de Python, por lo que no sé cómo depurar esto aún más. ¿Algún consejo?

Como justhalf señala arriba, mi pregunta aquí es esencialmente un duplicado de esta pregunta .

El contenido HTML se reportó a sí mismo como codificado en UTF-8 y, en su mayor parte, excepto por uno o dos caracteres UTF-8 no válidos.

Esto aparentemente confunde a BeautifulSoup acerca de qué encoding está en uso, y cuando se intenta descodificar por primera vez como UTF-8 al pasar el contenido a BeautifulSoup de esta manera:

 soup = BeautifulSoup(response.read().decode('utf-8')) 

Me gustaría obtener el error:

 UnicodeDecodeError: 'utf8' codec can't decode bytes in position 186812-186813: invalid continuation byte 

Al observar más de cerca la salida, hubo una instancia del carácter Ü que se codificó erróneamente como la secuencia de bytes no válida 0xe3 0x9c , en lugar del 0xc3 0x9c correcto.

Como lo sugiere la respuesta con la calificación más alta en esa pregunta, los caracteres UTF-8 no válidos se pueden eliminar durante el análisis, de modo que solo se pasen datos válidos a BeautifulSoup:

 soup = BeautifulSoup(response.read().decode('utf-8', 'ignore')) 

Codificar el resultado en utf-8 parece funcionar para mí:

 print (soup.find('div', id='navbutton_account')['title']).encode('utf-8') 

Cede:

 Hier können Sie sich kostenlos registrieren und / oder einloggen!