Не могу открыть Unicode URL с Python
Используя Python 2.5.2 и Linux Debian, я пытаюсь получить контент из испанского URL, который содержит испанский символ ('í'):
импорт urllib url = u'http://mydomain.es/índice.html' content = urllib.urlopen(url).read()
Я получаю эту ошибку:
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe1' in position 8: ordinal not in range(128)
Я пытался использовать перед передачей URL, чтобы urllib это:
url = urllib.quote(url)
и это:
url = url.encode('UTF-8')
но это не работает
можешь сказать что я делаю не так?
4 ответа
Согласно применимому стандарту RFC 1378, URL-адреса могут содержать только символы ASCII. Хорошее объяснение здесь, и я цитирую:
"... Только буквенно-цифровые символы [0-9a-zA-Z], специальные символы"$-_.+!*'()," [Не включая кавычки - ed] и зарезервированные символы, используемые для их зарезервированных целей, могут использоваться в незашифрованном виде в URL."
Как объясняют приведенные мною URL, это, вероятно, означает, что вам придется заменить этот "строчный i с острым акцентом" на "%ED".
Это работает для меня:
#!/usr/bin/env python
# define source file encoding, see: http://www.python.org/dev/peps/pep-0263/
# -*- coding: utf-8 -*-
import urllib
url = u'http://example.com/índice.html'
content = urllib.urlopen(url.encode("UTF-8")).read()
Кодирование URL как utf-8, должно было сработать. Интересно, правильно ли закодирован ваш исходный файл и знает ли его интерпретатор. Если ваш исходный файл Python, например, сохранен как UTF-8, то вы должны иметь
# coding=UTF-8
как первая или вторая строка.
import urllib
url = u'http://mydomain.es/índice.html'
content = urllib.urlopen(url.encode('utf-8')).read()
работает для меня.
Редактируйте: также, имейте в виду, что текст Unicode в интерактивном сеансе Python (через IDLE или консоль) сопряжен с трудностями, связанными с кодированием. В этих случаях вы должны использовать литералы Unicode (например, \u00ED в вашем случае).
Меня устраивает. Убедитесь, что вы используете довольно свежую версию Python, и ваша кодировка файла правильная. Вот мой код:
# -*- coding: utf-8 -*-
import urllib
url = u'http://mydomain.es/índice.html'
url = url.encode('utf-8')
content = urllib.urlopen(url).read()
(mydomain.es не существует, поэтому поиск DNS завершается неудачно, но на данный момент нет проблем с юникодом.)
У меня сейчас похожий случай. Пытаюсь скачать изображения. Я получаю URL-адреса с сервера в файле JSON. Некоторые изображения содержат символы, отличные от ASCII. Это вызывает ошибку:
for image in product["images"]:
filename = os.path.basename(image)
filepath = product_path + "/" + filename
urllib.request.urlretrieve(image, filepath) # error!
UnicodeEncodeError: кодек 'ascii' не может кодировать символ '\xc7' в позиции...
Я пробовал использовать .encode("UTF-8")
, но не могу сказать, что это помогло:
# coding=UTF-8
import urllib
url = u"http://example.com/wp-content/uploads/2018/09/İMAGE-1.png"
url = url.encode("UTF-8")
urllib.request.urlretrieve(url, "D:\image-1.jpg")
Это просто вызывает еще одну ошибку:
TypeError: нельзя использовать строковый шаблон для байтового объекта
Затем я дал urllib.parse.quote(url)
тому назад:
import urllib
url = "http://example.com/wp-content/uploads/2018/09/İMAGE-1.png"
url = urllib.parse.quote(url)
urllib.request.urlretrieve(url, "D:\image-1.jpg")
и снова возникает еще одна ошибка:
ValueError: неизвестный тип URL: 'http%3A//example.com/wp-content/uploads/2018/09/%C4%B0MAGE-1.png'
В :
в "http://..."
тоже сбежал, и я думаю, что это причина проблемы.
Итак, я нашел обходной путь. Я просто цитирую / экранирую путь, а не весь URL.
import urllib.request
import urllib.parse
url = "http://example.com/wp-content/uploads/2018/09/İMAGE-1.png"
url = urllib.parse.urlparse(url)
url = url.scheme + "://" + url.netloc + urllib.parse.quote(url.path)
urllib.request.urlretrieve(url, "D:\image-1.jpg")
Вот как выглядит URL: "http://example.com/wp-content/uploads/2018/09/%C4%B0MAGE-1.png"
, и теперь я могу скачать изображение.