Подтвердить что ты не робот

Что такое хороший, надежный короткий способ получить кодировку веб-страницы?

Я немного удивлен, что так сложно получить кодировку веб-страницы с Python. Я пропустил путь? HTTPMessage имеет множество функций, но не это.

>>> google = urllib2.urlopen('http://www.google.com/')
>>> google.headers.gettype()
'text/html'
>>> google.headers.getencoding()
'7bit'
>>> google.headers.getcharset()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: HTTPMessage instance has no attribute 'getcharset'

Итак, вы должны получить заголовок и разделить его. Дважды.

>>> google = urllib2.urlopen('http://www.google.com/')
>>> charset = 'ISO-8859-1'
>>> contenttype = google.headers.getheader('Content-Type', '')
>>> if ';' in contenttype:
...     charset = contenttype.split(';')[1].split('=')[1]
>>> charset
'ISO-8859-1'

Это удивительное количество шагов для такой основной функции. Я что-то пропустил?

4b9b3361

Ответ 2

Я провел некоторое исследование и придумал это решение:

response = urllib.request.urlopen(url)
encoding = response.headers.get_content_charset()

Вот как я это сделал бы в Python 3. Я не тестировал его в Python 2, но я предполагаю, что вам придется использовать urllib2.request вместо urllib.request.

Вот как это работает, поскольку официальная документация на Python не очень хорошо объясняет это: результат urlopen - это < объект href= "https://docs.python.org/3/library/http.client.html#httpresponse-objects" rel= "nofollow" > http.client.HTTPResponse. Свойством headers этого объекта является объект http.client.HTTPMessage, который, согласно документации, "реализуется с помощью email.message.Message class ", который имеет метод get_content_charset, который пытается определить и вернуть набор символов ответа.

По умолчанию этот метод возвращает None, если он не может определить набор символов, но вы можете переопределить это поведение, передав параметр failobj:

encoding = response.headers.get_content_charset(failobj="utf-8")

Ответ 3

Вы ничего не пропустили. Он делает правильные вещи - кодирование ответа HTTP является подразделением Content-Type.

Обратите внимание, что некоторые страницы могут отправлять только Content-Type: text/html, а затем установить кодировку с помощью <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> - что уродливое взломать хотя (со стороны автора страницы) и не слишком распространено.

Ответ 4

Я бы пошел с chardet Универсальный детектор кодирования.

>>> import urllib
>>> urlread = lambda url: urllib.urlopen(url).read()
>>> import chardet
>>> chardet.detect(urlread("http://google.cn/"))
{'encoding': 'GB2312', 'confidence': 0.99}

Вы правы, но ваш подход не удался для страниц, где charset объявлен в теге meta или вообще не объявлен.
Если вы посмотрите ближе к источникам Chardet, у него есть модули charsetprober/charsetgroupprober, которые прекрасно справляются с этой проблемой.