Urllib2 читается в Unicode

Мне нужно сохранить содержимое сайта, который может быть на любом языке. И мне нужно иметь возможность искать содержимое для строки Unicode.

Я пробовал что-то вроде:

import urllib2

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

Содержимое представляет собой поток байтов, поэтому я могу найти его для строки Unicode.

Мне нужно, чтобы когда я делал urlopen, а затем читал, чтобы использовать кодировку из заголовков для декодирования содержимого и кодирования его в UTF-8.

Ответ 1

После выполненных операций вы увидите:

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

и так:

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

ucontent теперь является строкой Unicode (из 140655 символов) - так, например, чтобы отобразить ее часть, если ваш терминал UTF-8:

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

и вы можете искать и т.д. и т.д.

Edit: Unicode I/O обычно сложнее (возможно, это то, что поднимает первоначальный вопрос), но я собираюсь обойти сложную проблему ввода строк Unicode в интерактивный интерпретатор Python (полностью не связанный с исходным вопросом) чтобы показать, как, как только строка Юникода правильно введена (я делаю это по кодовым точкам - тупой, но не сложный;-), поиск абсолютно без проблем (и, следовательно, мы надеемся, что исходный вопрос был тщательно отреагирован). Опять же, предполагая терминал UTF-8:

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

Примечание. Имейте в виду, что этот метод может не работать для всех сайтов, так как некоторые сайты указывают только кодировку символов внутри обслуживаемых документов (например, с помощью мета-тегов http-equiv).

Ответ 2

Чтобы разобрать Content-Type http-заголовок, вы можете использовать функцию 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)

Другой способ получить кодировку:

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

Или в Python 3:

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

Кодировка символов также может быть указана внутри html-документа, например, <meta charset="utf-8">.