urllib
モジュールを使用してgetリクエストを送信できるようにURLを作成しようとしています。
私の_final_url
_は
_url = "www.example.com/find.php?data=http%3A%2F%2Fwww.stackoverflow.com&search=Generate+value"
_
これを達成するために、私は次の方法を試しました。
_>>> initial_url = "http://www.stackoverflow.com"
>>> search = "Generate+value"
>>> params = {"data":initial_url,"search":search}
>>> query_string = urllib.urlencode(params)
>>> query_string
'search=Generate%2Bvalue&data=http%3A%2F%2Fwww.stackoverflow.com'
_
私の_query_string
_を_final_url
_の形式と比較すると、2つのことがわかります。
1)data=()&search=
ではなくパラメータの順序が逆になっていますsearch=()&data=
2)urlencode
も_+
_を_Generate+value
_にエンコードしました
最初の変更は、辞書のランダムな動作によるものだと思います。だから、私は OrderedDict
を使って辞書を逆にする を使うことを考えました。として、私は_python 2.6.5
_を使用しています
_pip install ordereddict
_
しかし、試してみるとコードで使用できません
_>>> od = OrderedDict((('a', 'first'), ('b', 'second')))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'OrderedDict' is not defined
_
だから、私の質問は、python 2.6.5でOrderedDict
を使用する正しい方法は何ですか?また、urlencode
が_+
_を無視するようにするにはどうすればよいですか? _Generate+value
_で。
また、これはURL
を構築するための正しいアプローチですか。
+
のエンコードについて心配する必要はありません。URLをエスケープ解除した後、サーバーに復元する必要があります。名前付きパラメーターの順序も重要ではありません。
OrderedDictを考慮すると、Pythonに組み込まれているわけではありません。collections
からインポートする必要があります。
from urllib import urlencode, quote
# from urllib.parse import urlencode # python3
from collections import OrderedDict
initial_url = "http://www.stackoverflow.com"
search = "Generate+value"
query_string = urlencode(OrderedDict(data=initial_url,search=search))
url = 'www.example.com/find.php?' + query_string
pythonが古すぎるで、モジュールcollections
にOrderedDictがない場合は、次を使用します。
encoded = "&".join( "%s=%s" % (key, quote(parameters[key], safe="+"))
for key in ordered(parameters.keys()))
とにかく、パラメータの順序は重要ではありません。
safe
のquote
パラメーターに注意してください。 +
がエスケープされるのを防ぎますが、サーバーがGenerate+value
をGenerate value
として解釈することを意味します。 +
を書き込み、%2B
を安全な文字としてマークすることにより、手動で%
をエスケープできます。
まず、httpリクエストのパラメータの順序は完全に無関係である必要があります。そうでない場合は、反対側の解析ライブラリが何か問題を抱えています。
次に、もちろん+
がエンコードされます。 +
は、エンコードされたURLのスペースのプレースホルダーとして使用されるため、生の文字列に+
が含まれている場合は、これをエスケープする必要があります。 urlencode
はエンコードされていない文字列を想定しているため、すでにエンコードされている文字列を渡すことはできません。
質問と他の回答に関するいくつかのコメント:
urllib.urlencode
_で順序を保持したい場合は、mapping(dict)の代わりにk/vペアの順序付けられたシーケンスを送信します。 dictを渡すと、urlencode
はfoo.items()
を呼び出して反復可能なシーケンスを取得します。# urllib.urlencode accepts a mapping or sequence # the output of this can vary, because `items()` is called on the dict urllib.urlencode({"data": initial_url,"search": search}) # the output of this will not vary urllib.urlencode((("data", initial_url), ("search", search)))
また、secondard doseq
引数を渡して、反復可能な値の処理方法を調整することもできます。
パラメータの順序は関係ありません。これらの2つのURLを例にとってみましょう。
https://example.com?foo=bar&bar=foohttps://example.com?bar=foo&foo=bar
Httpサーバーは、これらのパラメーターの順序は無関係であると見なす必要がありますが、URLを比較するように設計された関数はそうではありません。 URLを安全に比較するには、これらのパラメータを並べ替える必要があります。
ただし、重複するキーを検討してください。
URI仕様は重複キーをサポートしていますが、優先順位や順序には対応していません。
特定のアプリケーションでは、これらはそれぞれ異なる結果をトリガーし、同様に有効である可能性があります。
_https://example.com?foo=1&foo=2&foo=3
https://example.com?foo=1&foo=3&foo=2
https://example.com?foo=2&foo=3&foo=1
https://example.com?foo=2&foo=1&foo=3
https://example.com?foo=3&foo=1&foo=2
https://example.com?foo=3&foo=2&foo=1
_
+
_は、スペースをurlencoded形式で表す予約文字です(パスの一部の_%20
_に対して)。 _urllib.urlencode
_は、urllib.quote_plus()
ではなくurllib.quote()
を使用してエスケープします。 OPはおそらくこれを実行したかっただけです。initial_url = "http://www.stackoverflow.com" search = "Generate value" urllib.urlencode((("data", initial_url), ("search", search)))
生成するもの:
_data=http%3A%2F%2Fwww.stackoverflow.com&search=Generate+value
_
出力として。