urllib2 leído a Unicode


Necesito almacenar el contenido de un sitio que puede estar en cualquier idioma. Y necesito poder buscar en el contenido una cadena Unicode.

He intentado algo como:

import urllib2

req = urllib2.urlopen('http://lenta.ru')
content = req.read()

El contenido es un flujo de bytes, por lo que puedo buscar una cadena Unicode.

Necesito de alguna manera que cuando lo haga urlopen y luego lea para usar el conjunto de caracteres de los encabezados para decodificar el contenido y codificarlo en UTF-8.

Author: kiamlaluno, 2009-06-20

2 answers

Después de las operaciones que realizó, verá:

>>> req.headers['content-type']
'text/html; charset=windows-1251'

Y así:

>>> encoding=req.headers['content-type'].split('charset=')[-1]
>>> ucontent = unicode(content, encoding)

ucontent ahora es una cadena Unicode (de 140655 caracteres) so así que por ejemplo para mostrar una parte de ella, si su terminal es UTF-8:

>>> print ucontent[76:110].encode('utf-8')
<title>Lenta.ru: Главное: </title>

Y puedes buscar, etc, etc.

Editar: La E/S Unicode suele ser complicada (esto puede ser lo que está retrasando el asker original), pero voy a evitar el difícil problema de ingresar cadenas Unicode a un intérprete interactivo de Python (completamente no relacionado con la pregunta original) para mostrar cómo, una vez que una cadena Unicode SE introduce correctamente (lo estoy haciendo por puntos de código goo tonto pero no complicado; -), la búsqueda es absolutamente una obviedad (y por lo tanto espero que la pregunta original haya sido completamente contestada). Otra vez asumiendo un terminal UTF-8:

>>> x=u'\u0413\u043b\u0430\u0432\u043d\u043e\u0435'
>>> print x.encode('utf-8')
Главное
>>> x in ucontent
True
>>> ucontent.find(x)
93

Nota : Tenga en cuenta que este método puede no funcionar para todos los sitios, ya que algunos sitios solo especifican la codificación de caracteres dentro de los documentos servidos (usando etiquetas meta http-equiv, para ejemplo).

 97
Author: Alex Martelli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-19 10:47:49

Para analizar el encabezado http Content-Type, puede usar la función cgi.parse_header:

import cgi
import urllib2

r = urllib2.urlopen('http://lenta.ru')
_, params = cgi.parse_header(r.headers.get('Content-Type', ''))
encoding = params.get('charset', 'utf-8')
unicode_text = r.read().decode(encoding)

Otra forma de obtener el conjunto de caracteres:

>>> import urllib2
>>> r = urllib2.urlopen('http://lenta.ru')
>>> r.headers.getparam('charset')
'utf-8'

O en Python 3:

>>> import urllib.request
>>> r = urllib.request.urlopen('http://lenta.ru')
>>> r.headers.get_content_charset()
'utf-8'

La codificación de caracteres también se puede especificar dentro del documento html, por ejemplo, <meta charset="utf-8">.

 9
Author: jfs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-22 04:02:19