12

のようなUnicode文字列が'%C3%A7%C3%B6asd+fjkls%25asd'あり、この文字列をデコードしたいと思います。
使用urllib.unquote_plus(str)しましたが、うまくいきません。

  • 期待される :çöasd+fjkls%asd
  • 結果 :çöasd fjkls%asd

二重にコード化されたutf-8文字(%C3%A7および%C3%B6)は誤ってデコードされます。
私のPythonバージョンはLinuxディストリビューションで2.7です。期待される結果を得る最良の方法は何ですか?

4

6 に答える 6

29

あなたには3つか4つか5つの問題があります...しかしrepr()そしてunicodedata.name()あなたの友達です。の結果を伝達するさまざまなコンソールエンコーディングを持つ人々によって引き起こされる混乱なしに、それらはあなたが得たものを正確にあなたに明確に示しますprint fubar

概要:(a)Unicodeオブジェクトから開始し、それにunquote関数を適用するか、(b)strオブジェクトから開始し、コンソールエンコーディングがUTF-8ではないかのいずれかです。

あなたが言うようにあなたがユニコードオブジェクトから始めるならば:

>>> s0 = u'%C3%A7%C3%B6asd+fjkls%25asd'
>>> print repr(s0)
u'%C3%A7%C3%B6asd+fjkls%25asd'

これは偶然のナンセンスです。これに適用urllibX.unquote_YYYY()すると、別の意味のないUnicodeオブジェクト(u'\xc3\xa7\xc3\xb6asd+fjkls%asd')が表示され、印刷時に表示される症状が発生します。元のUnicodeオブジェクトをすぐにstrオブジェクトに変換する必要があります。

>>> s1 = s0.encode('ascii')
>>> print repr(s1)
'%C3%A7%C3%B6asd+fjkls%25asd'

次に、引用符を外す必要があります。

>>> import urllib2
>>> s2 = urllib2.unquote(s1)
>>> print repr(s2)
'\xc3\xa7\xc3\xb6asd+fjkls%asd'

その最初の4バイトを見ると、UTF-8でエンコードされています。そうすると、コンソールがUTF-8を期待している場合print s2は問題ないように見えますが、ISO-8859-1(別名latin1)を期待している場合は、症候性のゴミが表示されます(最初の文字はAチルダになります)。その考えを少しの間駐車して、Unicodeオブジェクトに変換しましょう。

>>> s3 = s2.decode('utf8')
>>> print repr(s3)
u'\xe7\xf6asd+fjkls%asd'

それを調べて、実際に何が得られるかを確認します。

>>> import unicodedata
>>> for c in s3[:6]:
...     print repr(c), unicodedata.name(c)
...
u'\xe7' LATIN SMALL LETTER C WITH CEDILLA
u'\xf6' LATIN SMALL LETTER O WITH DIAERESIS
u'a' LATIN SMALL LETTER A
u's' LATIN SMALL LETTER S
u'd' LATIN SMALL LETTER D
u'+' PLUS SIGN

あなたが期待したと言ったことのように見えます。次に、コンソールに表示するかどうかという問題が発生します。注:「cp850」が表示されても、びっくりしないでください。私はこれを移植可能に行っており、たまたまWindowsのコマンドプロンプトでこれを行っています。

>>> import sys
>>> sys.stdout.encoding
'cp850'
>>> print s3
çöasd+fjkls%asd

注:Unicodeオブジェクトは、sys.stdout.encodingを使用して明示的にエンコードされました。幸い、のすべてのUnicode文字はs3、そのエンコーディング(およびcp1252とlatin1)で表現できます。

于 2011-02-28T10:02:02.600 に答える
12

unquoteまたはを使用するunquote_plusと、バイト文字列が得られます。Unicode文字列が必要な場合は、バイト文字列をUnicodeにデコードする必要があります。

>>> print(urllib.unquote_plus('%C3%A7%C3%B6asd+fjkls%25asd').decode('utf8'))
çöasd fjkls%asd
>>> 

と比べて:

>>> print(urllib.unquote_plus('%C3%A7%C3%B6asd+fjkls%25asd'))
çöasd fjkls%asd
>>> 

入力文字列はバイト文字列でなければならないことに注意してください。Unicodeをに渡すとunquote/unquote_plus、少し混乱します。この場合は、最初にエンコードします。

>>> print(urllib.unquote_plus(u'%C3%A7%C3%B6asd+fjkls%25asd'.encode('ascii')).decode('utf8'))
çöasd fjkls%asd
于 2011-02-28T09:00:55.627 に答える
0

もう一度お試しくださいurllib2

print urllib2.unquote('%C3%A7%C3%B6asd+fjkls%25asd')
于 2011-02-28T07:33:29.607 に答える
0

'%C3%A7%C3%B6asd + fjkls%25asd'-これはUnicode文字列ではありません。

これはURLエンコードされた文字列です。代わりにurllib2.unquote()を使用してください。

于 2011-02-28T07:43:58.720 に答える
0

2つの問題があります。文字列はUnicodeでエンコードされており、文字がurlencodedで含まれています。いくつか一致します。文字列をascciに正規化して、正しく解釈されないようにすることができます。

>>> s = '%C3%A7%C3%B6asd+fjkls%25asd' # ascii string
>>> print urllib2.unquote(s) # works as expected
çöasd+fjkls%asd
>>> s = u'%C3%A7%C3%B6asd+fjkls%25asd' # unicode string
>>> print urllib2.unquote(s) # decode stuff that it shouldn't
çöasd+fjkls%asd
>>> print urllib2.unquote(s.encode('ascii')) # encode the unicode string to ascii: works!
çöasd+fjkls%asd
于 2011-02-28T08:14:52.800 に答える
-1

を考慮してに変換するunquote_plus方法を使用しています。メソッドを使用するだけで問題ありません。space+unquote

>>> import urllib
>>> print urllib.unquote('%C3%A7%C3%B6asd+fjkls%25asd')
çöasd+fjkls%asd
>>> print urllib.unquote_plus('%C3%A7%C3%B6asd+fjkls%25asd')
çöasd fjkls%asd
于 2011-02-28T07:50:21.893 に答える