Есть ли готовый jQuery-заменитель, который я могу использовать для urllib.quote и urllib.unquote в Python 2.6.5?
Python urllib.quote
и urllib.unquote
не корректно обрабатывают Unicode в Python 2.6.5. Вот что происходит:
In [5]: print urllib.unquote(urllib.quote(u'Cataño'))
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
/home/kkinder/<ipython console> in <module>()
/usr/lib/python2.6/urllib.pyc in quote(s, safe)
1222 safe_map[c] = (c in safe) and c or ('%%%02X' % i)
1223 _safemaps[cachekey] = safe_map
-> 1224 res = map(safe_map.__getitem__, s)
1225 return ''.join(res)
1226
KeyError: u'\xc3'
Кодирование значения для UTF8 также не работает:
In [6]: print urllib.unquote(urllib.quote(u'Cataño'.encode('utf8')))
Cataño
Он распознается как ошибка и существует исправление, но не для моей версии Python.
Что бы я хотел, это нечто похожее на urllib.quote/urllib.unquote, но корректно обрабатывает переменные Юникода, так что этот код будет работать:
decode_url(encode_url(u'Cataño')) == u'Cataño'
Любые рекомендации?
Ответы
Ответ 1
Python urllib.quote и urllib.unquote не обрабатывают Unicode правильно
urllib
не обрабатывает Unicode вообще. URL-адреса не содержат символов, отличных от ASCII, по определению. Когда вы имеете дело с urllib
, вы должны использовать только байтовые строки. Если вы хотите, чтобы они отображали символы Unicode, вам придется их кодировать и декодировать вручную.
IRI могут содержать символы не ASCII, кодируя их как последовательности UTF-8, но Python на данный момент не имеет irilib
.
Кодирование значения для UTF8 также не работает:
In [6]: print urllib.unquote(urllib.quote(u'Cataño'.encode('utf8')))
Cataño
А, ну, теперь вы вводите Unicode в консоль и делаете print
-Unicode на консоли. Обычно это ненадежно, особенно в Windows и в вашем случае с консолью IPython.
Введите длинный путь с помощью обратных косых последовательностей, и вы можете более легко увидеть, что бит urllib
действительно работает:
>>> u'Cata\u00F1o'.encode('utf-8')
'Cata\xC3\xB1o'
>>> urllib.quote(_)
'Cata%C3%B1o'
>>> urllib.unquote(_)
'Cata\xC3\xB1o'
>>> _.decode('utf-8')
u'Cata\xF1o'
Ответ 2
"" Кодирование значения для UTF8 также не работает "" "... результатом вашего кода является объект str
, который, по предположению, является входом, закодированным в UTF-8. Вам нужно его расшифровать или определить" не работает" - что вы ожидаете?
Примечание. Чтобы нам не нужно было угадывать кодировку вашего терминала и тип ваших данных, используйте print repr(whatever)
вместо print whatever
.
>>> # Python 2.6.6
... from urllib import quote, unquote
>>> s = u"Cata\xf1o"
>>> q = quote(s.encode('utf8'))
>>> u = unquote(q).decode('utf8')
>>> for x in (s, q, u):
... print repr(x)
...
u'Cata\xf1o'
'Cata%C3%B1o'
u'Cata\xf1o'
>>>
Для сравнения:
>>> # Python 3.2
... from urllib.parse import quote, unquote
>>> s = "Cata\xf1o"
>>> q = quote(s)
>>> u = unquote(q)
>>> for x in (s, q, u):
... print(ascii(x))
...
'Cata\xf1o'
'Cata%C3%B1o'
'Cata\xf1o'
>>>
Ответ 3
Я столкнулся с той же проблемой и использовал вспомогательную функцию для работы с функцией non-ascii и urllib.urlencode(которая включает в себя цитату и unquote):
def utf8_urlencode(params):
import urllib as u
# problem: u.urlencode(params.items()) is not unicode-safe. Must encode all params strings as utf8 first.
# UTF-8 encodes all the keys and values in params dictionary
for k,v in params.items():
# TRY urllib.unquote_plus(artist.encode('utf-8')).decode('utf-8')
if type(v) in (int, long, float):
params[k] = v
else:
try:
params[k.encode('utf-8')] = v.encode('utf-8')
except Exception as e:
logging.warning( '**ERROR utf8_urlencode ERROR** %s' % e )
return u.urlencode(params.items()).decode('utf-8')
принят из Кодирование/декодирование Unicode URL с Python
Ответ 4
Итак, у меня была та же проблема: я хотел поместить параметры запроса в URL-адрес, но некоторые из них содержали странные символы (диакритики).
Работа с кодировкой давала грязный url и была хрупкой.
Мое решение заключалось в замене каждого символа акцента/странного юникода на его эквивалент ascii. Это легко благодаря unidecode
: Каков наилучший способ удаления акцентов в строке юникода Python?
pip install unidecode
затем
from unidecode import unidecode
print unidecode(u"éèê")
# prints eee
поэтому у меня есть чистый URL. Также работает для китайцев и т.д.