48

Pythonで引数をエンコード、保存、デコードしようとしていますが、途中で迷子になっています。これが私のステップです:

1)私はグーグルツールキットを使用gtm_stringByEscapingForURLArgumentして、HTTP引数に渡すためにNSStringを適切に変換します。

2)私のサーバー(python)では、これらの文字列引数を次のように保存します(u'1234567890-/:;()$&@".,?!\'[]{}#%^*+=_\\|~<>\u20ac\xa3\xa5\u2022.,?!\''これらは、「123」ビューと「#+ =」ビューのiphoneキーパッドの標準キーであり、そこにある文字\u\x文字であることに注意してください)ポンド、円などのいくつかの金銭的な接頭辞)

3)私はurllib.quote(myString,'')その保存された値を呼び出します。おそらく、クライアントへの転送のためにそれらを%エスケープして、クライアントがそれらをパーセントでエスケープできないようにします。

その結果、%エスケープの結果をログに記録しようとすると、例外が発生します。httpを送信するために適切に変換するために、\ uおよび\x形式で保存された値に適用する必要がある、私が見落としている重要なステップはありますか?

更新:以下の答えとしてマークされた提案は私のために働いた。ただし、以下のコメントに対応するために、いくつかの更新を提供しています。

私が受け取った例外は、の問題を引用しました\u20ac。それが文字列の最初のUnicode文字であったという事実ではなく、それが特に問題であったかどうかはわかりません。

その\u20ac文字は「ユーロ」記号のUnicodeです。基本的に、urllib2quoteメソッドを使用しない限り、問題が発生することがわかりました。

4

3 に答える 3

71

「生の」ユニコードをエンコードするurlは実際には意味がありません。あなたがする必要があるのは.encode("utf8")、最初にあなたが既知のバイトエンコーディングを持っているようにすることであり、それからそれ.quote()です。

出力はあまりきれいではありませんが、正しいuriエンコーディングである必要があります。

>>> s = u'1234567890-/:;()$&@".,?!\'[]{}#%^*+=_\|~<>\u20ac\xa3\xa5\u2022.,?!\''
>>> urllib2.quote(s.encode("utf8"))
'1234567890-/%3A%3B%28%29%24%26%40%22.%2C%3F%21%27%5B%5D%7B%7D%23%25%5E%2A%2B%3D_%5C%7C%7E%3C%3E%E2%82%AC%C2%A3%C2%A5%E2%80%A2.%2C%3F%21%27'

デバッグ中などの場合は、正しく印刷するために両方unquote()とこれを行う必要があることを忘れないでください。decode()

>>> print urllib2.unquote(urllib2.quote(s.encode("utf8")))
1234567890-/:;()$&@".,?!'[]{}#%^*+=_\|~<>€£¥•.,?!'
>>> # oops, nasty  means we've got a utf8 byte stream being treated as an ascii stream
>>> print urllib2.unquote(urllib2.quote(s.encode("utf8"))).decode("utf8")
1234567890-/:;()$&@".,?!'[]{}#%^*+=_\|~<>€£¥•.,?!'

実際、これは別の回答で言及されているdjango関数が行うことです。

関数django.utils.http.urlquote()およびdjango.utils.http.urlquote_plus()は、非ASCII文字で機能するPythonの標準urllib.quote()およびurllib.quote_plus()のバージョンです。(データはエンコード前にUTF-8に変換されます。)

それ以上引用符やエンコーディングを適用する場合は、物事を混乱させないように注意してください。

于 2010-08-25T11:48:13.973 に答える
4

2番目のpycruftの発言をしたいと思います。Webプロトコルは数十年にわたって進化しており、さまざまな規則のセットを処理するのは面倒な場合があります。現在、URLは文字に対して明示的に定義されておらず、バイト(オクテット)に対してのみ定義されています。歴史的な偶然の一致として、URLは、エンコーディングが存在することを強制したり、安全に期待したりすることはできませんが、想定できる場所の1つです。ただし、ここでは他のエンコーディングよりもlatin-1とutf-8を優先する規則があります。しばらくの間、「ユニコードパーセントエスケープ」は未来のように見えましたが、彼らは決して追いつきませんでした。

unicodeオブジェクトとオクテットの違いについて、この領域で慎重に注意を払うことが最も重要ですstr(Python <3.0の場合、つまり、紛らわしいことに、 PythonのstrUnicodeオブジェクトおよびbytes/bytearrayオブジェクト> = 3.0)。残念ながら、私の経験では、Python 2.xで2つの概念を明確に分離することは、いくつかの理由でかなり困難です。

さらに多くのOT、サードパーティのHTTPリクエストを受信したい場合、パーセントエスケープされたutf-8エンコードオクテットで送信されるURLに完全に依存することはできません。そこには時折%uxxxxエスケープがあり、少なくともFirefoxが存在する可能性があります。 2.xは、URLを可能な場合はlatin-1として、必要な場合はutf-8としてのみエンコードするために使用されていました。

于 2010-08-25T14:40:28.807 に答える
2

stdlibで運が悪かったので、urllib.quoteはUnicodeでは機能しません。djangoを使用している場合は、ユニコードで適切に機能するdjango.utils.http.urlquoteを使用できます。

于 2010-08-25T06:33:23.977 に答える