Не могу открыть 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", и теперь я могу скачать изображение.

Другие вопросы по тегам