Urllib для python 3

Этот код в python3 проблематичен:

import urllib.request
fhand=urllib.request.urlopen('http://www.py4inf.com/code/romeo.txt')
print(fhand.read())

Его вывод:

b'But soft what light through yonder window breaks'
b'It is the east and Juliet is the sun'
b'Arise fair sun and kill the envious moon'
b'Who is already sick and pale with grief'

Почему я получил b'...'? Что я могу сделать, чтобы получить правильный ответ?

Правильный текст должен быть

But soft what light through yonder window breaks
It is the east and Juliet is the sun
Arise fair sun and kill the envious moon
Who is already sick and pale with grief

Ответ 1

b'...' представляет собой байтовую строку: массив байтов, а не настоящую строку.

Чтобы преобразовать в реальную строку, используйте

fhand.read().decode()

Используется кодировка по умолчанию UTF-8. Для кодирования ASCII используйте

fhand.read().decode("ASCII")

например

Ответ 2

Как в документации говорится, urlopen возвращает объект, метод read дает вам последовательность байтов, а не последовательность символов, Чтобы преобразовать байты в печатные символы, что вам нужно, вам нужно применить метод decode, используя кодировку, в которой находятся байты.

Причина, по которой кажется смысл, заключается в том, что кодировка по умолчанию, выбранная Python для отображения байтов, оказывается правильной или, по крайней мере, соответствует правильной для этих символов.

Чтобы сделать это правильно, вы должны read().decode(encoding), где encoding - это значение кодировки из заголовка Content-Type HTTP, доступное через HTTPResponse объект (т.е. fhand, в вашем коде). Если нет заголовка Content-Type или если он не указывает кодировку, вы уменьшите до угадывание, какая кодировка использовать, но для типичного английского текста это не имеет значения, и во многих других случаях это, вероятно, будет UTF-8.

Ответ 3

Python 3 различает байтовые последовательности и строки. "B" перед строкой сообщает вам, что urllib вернул содержимое как "сырые" байты. Возможно, стоит заглянуть в ситуацию с python 3 байтами/строками, но в основном вы получили правильный текст. Если вы не хотите, чтобы результат был байтом, вам просто нужно преобразовать его в "реальную" строку python.

Ответ 4

Сторонняя библиотека requests обрабатывает декодирование в строки Unicode автоматически. Он делает все возможное, чтобы вывести правильное кодирование, поэтому вам не нужно заранее угадывать кодировку.

>>> import requests
>>> r = requests.get('http://www.py4inf.com/code/romeo.txt')
>>> print(r.text)
But soft what light through yonder window breaks
It is the east and Juliet is the sun
Arise fair sun and kill the envious moon
Who is already sick and pale with grief

То же самое с urllib.request и предполагаемой UTF-8 кодировкой:

>>> from urllib.request import urlopen
>>> r = urlopen('http://www.py4inf.com/code/romeo.txt')
>>> print(r.read().decode('UTF-8'))
But soft what light through yonder window breaks
It is the east and Juliet is the sun
Arise fair sun and kill the envious moon
Who is already sick and pale with grief