2009-06-20 25 views
45

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

He intentado algo así como:

import urllib2 

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

El contenido es una secuencia de bytes, por lo que puede buscar por una cadena Unicode.

Necesito de alguna manera que cuando hago urlopen y luego leo para usar el juego de caracteres de los encabezados para decodificar el contenido y codificarlo en UTF-8.

+0

La codificación se realiza utilizando una función de la biblioteca urllib no de urllib2. De http://www.voidspace.org.uk/python/articles/urllib2.shtml#headers – Macarse

+1

@Macarse esta no es la codificación a la que se refiere Vitaly, se refiere a la decodificación y codificación del contexto de solicitud real con '[byte string] '. decode (' [charset] ') y u' [cadena unicode] '. encode (' utf-8 '). Se refiere a los parámetros de solicitud de codificación. –

+0

relacionado: [Una buena forma de obtener el conjunto de caracteres/codificación de una respuesta HTTP en Python] (http://stackoverflow.com/q/14592762/4279) – jfs

Respuesta

96

Después de las operaciones que ha realizado, 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 es ahora una cadena Unicode (de 140655 caracteres) - así 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 se puede buscar, etc, etc.

Edición: Unicode I/O suele ser complicado (esto puede ser lo que está reteniendo el asker original) pero voy a eludir el difícil problema de ingresar cadenas Unicode a un intérprete interactivo de Python (sin relación con la pregunta original)) para mostrar cómo, una vez que se ingresa correctamente una cadena Unicode (lo hago por puntos de código - tonto pero no complicado ;-), la búsqueda es absolutamente obvia (y espero que la pregunta original haya sido completamente respondida). asumiendo de nuevo 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 sólo especifican la codificación de caracteres dentro de los documentos servidos (utilizando etiquetas meta http-equiv , por ejemplo).

+0

Hola Alex, gracias por la respuesta. Pero si lo hago: u'Главное 'in ucontent devuelve False. ¿Hay una mejor manera de hacer la búsqueda? –

+2

¿Cómo está ingresando esa cadena u '...'? Unicode I/O es complicado, ya que su terminal AND Python debe estar en longitudes de onda idénticas. Usar los puntos de código Unicode explícitos (aburrido pero NO engañoso) funciona bien, déjame editar mi respuesta para mostrar eso. –

+0

Estoy ingresando usando la consola, si necesito hacer esto para una prueba de unidad, ¿qué debo configurar para la codificación: en la parte superior del archivo? –

9

Para analizar Content-Type cabecera HTTP, puede utilizar cgi.parse_header función:

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 juego 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' 

Carácter la codificación también se puede especificar dentro del documento html, por ejemplo, <meta charset="utf-8">.