web-dev-qa-db-fra.com

urllib2 lu en Unicode

J'ai besoin de stocker le contenu d'un site qui peut être dans n'importe quelle langue. Et je dois pouvoir rechercher le contenu pour une chaîne Unicode.

J'ai essayé quelque chose comme:

import urllib2

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

Le contenu est un flux d'octets, donc je peux le rechercher pour une chaîne Unicode.

J'ai besoin d'une manière que lorsque je fais urlopen et que je lis ensuite pour utiliser le jeu de caractères des en-têtes pour décoder le contenu et le coder en UTF-8.

46
Vitaly Babiy

Après les opérations que vous avez effectuées, vous verrez:

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

et donc:

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

ucontent est maintenant une chaîne Unicode (de 140655 caractères) - donc par exemple pour en afficher une partie, si votre terminal est UTF-8:

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

et vous pouvez rechercher, etc., etc.

Edit: les E/S Unicode sont généralement délicates (c'est peut-être ce qui retient le demandeur d'origine), mais je vais contourner le problème difficile de la saisie de chaînes Unicode dans un interpréteur interactif Python (complètement sans rapport avec la question d'origine) pour montrer comment, une fois une chaîne Unicode IS correctement entrée (je le fais par des codes - maladroit mais pas compliqué ;-), la recherche est absolument un non- brainer (et donc, espérons-le, la question d'origine a été résolue). En supposant à nouveau 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

Remarque: Gardez à l'esprit que cette méthode peut ne pas fonctionner pour tous les sites, car certains sites spécifient uniquement le codage des caractères à l'intérieur des documents servis (en utilisant des balises META http-equiv, par exemple).

99
Alex Martelli

Pour analyser Content-Type en-tête http, vous pouvez utiliser cgi.parse_header une fonction:

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)

Une autre façon d'obtenir le jeu de caractères:

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

Ou en Python 3:

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

Le codage des caractères peut également être spécifié dans le document html, par exemple, <meta charset="utf-8">.

10
jfs