14

urllibモジュールを使用してURLに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

OrderedDictだから、私の質問は、Python 2.6.5で使用する正しい方法は何ですか、そしてどのように私はでをurlencode無視する+ようにするのですかGenerate+value

また、これはビルドするための正しいアプローチですかURL

4

3 に答える 3

27

エンコードについて心配する必要はありません+。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が古すぎて、モジュールにOrderedDictがない場合は、次collectionsを使用します。

encoded = "&".join( "%s=%s" % (key, quote(parameters[key], safe="+")) 
    for key in ordered(parameters.keys()))

とにかく、パラメータの順序は重要ではありません。

safeのパラメータに注意してくださいquote。エスケープされるのを防ぎ+ますが、それは、サーバーがGenerate+valueとして解釈することを意味しますGenerate value。安全な文字として+書き込み%2Bとマークを付けることで、手動でエスケープできます。%

于 2012-05-26T11:11:55.863 に答える
4

まず、httpリクエストのパラメータの順序は完全に無関係である必要があります。そうでない場合は、反対側の解析ライブラリが何か問題を抱えています。

第二に、もちろん、+はエンコードされています。+はエンコードされたURLのスペースのプレースホルダーとして使用されるため、生の文字列にが含まれている場合は+、これをエスケープする必要があります。urlencodeエンコードされていない文字列が必要です。すでにエンコードされている文字列を渡すことはできません。

于 2012-05-26T11:12:58.357 に答える
1

質問と他の回答に関するいくつかのコメント:

  1. で順序を保持したい場合は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)))

また、secondarddoseq引数を渡して、反復可能な値の処理方法を調整することもできます。

  1. パラメータの順序は関係ありません。たとえば、次の2つのURLを取り上げます。

    https://example.com?foo=bar&bar=foo https://example.com?bar=foo&foo=bar

    httpサーバーは、これらのパラメーターの順序は無関係であると見なす必要がありますが、URLを比較するように設計された関数はそうではありません。URLを安全に比較するには、これらのパラメータを並べ替える必要があります。

    ただし、重複するキーを検討してください。

    https://example.com?foo=3&foo=2&foo=1

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
  1. +、urlencoded形式でスペースを表す予約文字です(%20パスの一部の場合とは異なります)。ではなく、urllib.urlencodeを使用してエスケープします。OPはおそらくこれを実行したかっただけです。urllib.quote_plus()urllib.quote()

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

出力として。

于 2017-03-29T23:53:16.210 に答える