Строить строку запроса с помощью urlencode python

Я пытаюсь создать URL-адрес, чтобы отправить запрос на получение с помощью модуля urllib .

Предположим, что мой 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 вы можете наблюдать две вещи

1) Порядок параметров инвертируется вместо data=()&search= it search=()&data=

2) urlencode также закодировал значение + в Generate+value

Я считаю, что первое изменение связано с случайным поведением словаря. Итак, я использую OrderedDict для 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 .

  • Кэширование urlib Python
  • Python: Получить HTTP-заголовки от вызова urllib2.urlopen?
  • Python; urllib error: AttributeError: объект 'bytes' не имеет атрибута 'read'
  • Urllib и проверка сертификата сервера
  • как проверить, соответствует ли urllib2 перенаправлению?
  • Почему я получаю атрибут AttributeError при попытке распечатать
  • Python 3 urllib создает TypeError: данные POST должны быть байтами или итерируемыми байтами. Это не может быть типа str
  • Ошибка Python при использовании urllib.open
  • 3 Solutions collect form web for “Строить строку запроса с помощью urlencode python”

    Вы не должны беспокоиться о кодировании + он должен быть восстановлен на сервере после отмены запроса. Порядок именованных параметров тоже не имеет значения.

    Учитывая 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)) 

    если ваш питон слишком стар и не имеет OrderedDict в collections модулей, используйте:

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

    Во всяком случае, порядок параметров не должен иметь значения.

    Обратите внимание на safe параметр quote . Он предотвращает + экранирование, но это означает, что сервер будет интерпретировать Generate+value как Generate value . Вы можете вручную избежать + , написав %2B и обозначив % как безопасный символ:

    Во-первых, порядок параметров в HTTP-запросе должен быть совершенно неактуальным. Если это не так, то библиотека разбора на стороне делает что-то неправильно.

    Во-вторых, конечно + кодируется. + используется в качестве заполнителя для пробела в закодированном URL-адресе, поэтому, если yor raw string содержит + , это должно быть экранировано. urlencode ожидает unencoded строку, вы не можете передать ей строку, которая уже закодирована.

    Некоторые комментарии по вопросу и другие ответы:

    1. Если вы хотите сохранить порядок с urllib.urlencode , отправьте упорядоченную последовательность пар k / v вместо сопоставления (dict). когда вы проходите в 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)))

    вы также можете передать второй аргумент doseq чтобы настроить, как обрабатываются итерируемые значения.

    1. Порядок параметров не имеет значения. возьмите эти два 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 форме (vs %20 для части пути). urllib.urlencode escapes использует 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

    как выход.

    Python - лучший язык программирования в мире.