web-dev-qa-db-ja.com

Python 2.6.5でurllib.quoteとurllib.unquoteに使用できるUnicode対応の代替品はありますか?

Pythonのurllib.quoteおよびurllib.unquote Python 2.6.5でUnicodeを正しく処理しない。これは何が起こるかである:

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に似ていますが、このコードが機能するように、Unicode変数を正しく処理します。

decode_url(encode_url(u'Cataño')) == u'Cataño'

何かお勧めですか?

41
Ken Kinder

Pythonのurllib.quoteおよびurllib.unquoteがUnicodeを正しく処理しない

urllibはUnicodeをまったく処理しません。定義上、URLには非ASCII文字は含まれません。 urllibを扱う場合は、バイト文字列のみを使用する必要があります。それらをUnicode文字で表す場合は、手動でエンコードおよびデコードする必要があります。

IRIs には非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'
43
bobince

"" "値をUTF8にエンコードすることもできません" "" ...コードの結果はstrオブジェクトで、UTF-8でエンコードされた入力と思われます。デコードするか、「機能しない」を定義する必要があります-doは何を期待していますか?

注:端末のエンコーディングとデータのタイプを推測する必要がないように、_print whatever_の代わりにprint repr(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'
>>>
_
5
John Machin

そのため、同じ問題が発生しました。クエリパラメータをURLに入れたいのですが、一部に奇妙な文字(発音記号)が含まれていました。

エンコーディングを処理すると、URLが乱雑になり、壊れやすくなりました。

私の解決策は、すべてのアクセント/奇妙なUnicode文字を同等のASCIIに置き換えることでした。 unidecodeのおかげで簡単です: Pythonユニコード文字列のアクセントを削除する最良の方法は何ですか?

pip install unidecode

その後

from unidecode import unidecode
print unidecode(u"éèê") 
# prints eee

だから私はきれいなURLを持っています。中国語などでも動作します.

1
Ehvince

私は同じ問題に遭遇し、ヘルパー関数を使用して非ASCIIおよびurllib.urlencode関数(引用と引用解除を含む)を処理しました。

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')

PythonでのUnicode URLエンコード/デコード から採用

1
Marc Maxmeister