2014-09-10 4 views
-2

Когда я построить такой код:UnicodeDecodeError с urllib.request объекта

import urllib.request 

with urllib.request.urlopen('http://google.ru') as url: 
    print(url.read().decode()) 

Я получил эту ошибку:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xcf in position 102: invalid continuation byte 

Что способ это исправить?

+1

Обратите внимание, что это не имеет никакого отношения к Sublime Text 3 *. ST3 запускает Python 3, и эта проблема одинакова на любом сеансе интерпретатора Python 3. –

ответ

3

Вы пытаетесь декодировать данные без указания кодека. В этом случае используется значение по умолчанию (UTF-8), и это значение по умолчанию неверно для этой страницы. Учитывая доменное имя, я ожидаю, что это будет Cyrillic encoding.

Если ответ включает правый кодек, он будет найден с url.info().get_charset(); он вернет None, если он не был установлен, и в этот момент HTML может содержать подсказку в <meta> tag; вам придется разобрать это вручную.

URL, который вы пытаетесь загрузить не включает в себя набор символов типа контента:

>>> import urllib.request 
>>> url = urllib.request.urlopen('http://google.ru') 
>>> url.info().get_charset() is None 
True 

Если ни <meta> тег, ни Content-Type CharacterSet было установлено, по умолчанию является Latin-1; это работает за указанный вами URL-адрес:

print(url.read().decode('latin1')) 

Однако, это, вероятно, даже не правильная кодировка; поскольку Latin-1 работает для всего контента. Скорее всего, вы получите Mochibake. В некоторых случаях вам может потребоваться жесткое кодирование; это похоже на кодировку CP-1251 (Windows Cyrilic codepage) для меня.

Если вы планируете анализировать HTML-код, используйте BeautifulSoup и передайте содержимое bytes; он будет автоматически определять кодировку для вас:

import urllib.request 
from bs4 import BeautifulSoup 

with urllib.request.urlopen('http://google.ru') as url: 
    soup = BeautifulSoup(url) 

Вы можете сказать, BeautifulSoup использовать определенную кодировку с from_encoding, если он получает неправильно автоопределение:

with urllib.request.urlopen('http://google.ru') as url: 
    soup = BeautifulSoup(url, from_encoding='cp1251') 

Демо:

>>> import urllib.request 
>>> from bs4 import BeautifulSoup 
>>> url = urllib.request.urlopen('http://google.ru') 
>>> soup = BeautifulSoup(url, from_encoding='cp1251') 
>>> soup.head.meta 
<meta content="Поиск информации в интернете: веб страницы, картинки, видео и многое другое." name="description"/> 

Должен сказать, что я удивлен, что Google не установил правильный набор символов контента для ответа здесь.

Смежные вопросы