Ваша проблема в том, что urlopen
возвращает байтово-ориентированный файлоподобный объект, в то время как io.open
ожидает ввода истинного текста (где "text" означает "unicode
на Python 2, str
на Python 3").
Единственное, что вам нужно изменить - это decode
результат вызова read
;по умолчанию он похож на байты, и вам нужен настоящий текст.Вам нужно выяснить правильную кодировку (либо жестко, либо явно проверяя заголовки, чтобы выяснить это), чтобы правильно ее декодировать (скорее всего, это UTF-8 или, что гораздо менее вероятно, cp1252, но это может быть что-то странное).
В любом случае, зная это, единственное изменение, которое вам нужно сделать, это изменить:
libro.write(archivo.read())
на:
libro.write(archivo.read().decode(knownencoding))
Если выВы уверены, что сервер всегда обеспечивает вывод UTF-8, тогда:
libro.write(archivo.read().decode('utf-8'))
достаточно.Да, это слегка расточительно (вы декодируете его только для записи в поток, который немедленно перекодирует его), но важно то, что это дает вам гарантию того, что полученные вами байты были интерпретированы как действительный UTF-8, который сбрасывает необработанные байты на дискне гарантирует.
Более сложное решение проверяет заголовки:
import urllib2
import io
import string
def n_palabras(x):
archivo = urllib2.urlopen(x)
# Find charset in headers, if it exists
for p in archivo.headers.plist:
key, sep, value = p.partition('=')
if sep and key.strip().lower() == 'charset':
encoding = value.strip()
break
else:
encoding = 'utf-8'
data = archivo.read()
try:
# Try to use parsed charset
data = data.decode(encoding)
except UnicodeDecodeError:
# If that fails, try UTF-8 as fallback; let exception bubble
# if this fails too
data = data.decode('utf-8')
with io.open("alice.txt", "w", encoding="utf-8") as libro:
libro.write(data)