Як urlencode запит рядка в Python?


552

Я намагаюся urlencode цього рядка, перш ніж надсилати.

queryString = 'eventName=' + evt.fields["eventName"] + '&' + 'eventDescription=' + evt.fields["eventDescription"]; 

Відповіді:


561

Вам потрібно передати свої параметри urlencode()як відображення (dict), або послідовність 2-кортезів, наприклад:

>>> import urllib
>>> f = { 'eventName' : 'myEvent', 'eventDescription' : 'cool event'}
>>> urllib.urlencode(f)
'eventName=myEvent&eventDescription=cool+event'

Python 3 або вище

Використання:

>>> urllib.parse.urlencode(f)
eventName=myEvent&eventDescription=cool+event

Зауважте, що це не робить кодування URL у загальновживаному сенсі (дивіться на вихід). Для цього використовуйте urllib.parse.quote_plus.


12
"Зауважте, що urllib.urlencode не завжди робить хитрість. Проблема полягає в тому, що деякі служби дбають про порядок аргументів, який втрачається під час створення словника. Для таких випадків urllib.quote_plus краще, як запропонував Рікі. "
Blairg23

16
Технічно це помилка в послугах, чи не так?
holdenweb

5
і як би це зробити, якщо ви просто хочете зробити безпечну URL-адресу рядка, не будуючи повний рядок аргументу запиту?
Майк 'Помакс' Камерманс

1
@ Mike'Pomax'Kamermans - дивись , наприклад , stackoverflow.com/questions/12082314 / ... або відповідь Ріки на це питання.
bgporter

1
@ bk0, здається, ваш метод дійсний лише для словників, а не для рядків.
JD Gamboa

1021

Пітон 2

Що ви шукаєте urllib.quote_plus:

>>> urllib.quote_plus('string_of_characters_like_these:$#@=?%^Q^$')
'string_of_characters_like_these%3A%24%23%40%3D%3F%25%5EQ%5E%24'

Пітон 3

У Python 3 urllibпакет був розбитий на більш дрібні компоненти. Ви будете використовувати urllib.parse.quote_plus(зверніть увагу на parseдочірній модуль)

import urllib.parse
urllib.parse.quote_plus(...)

4
Дякую! У моєму випадку, проте, мені потрібно покласти:import urllib.parse ... urllib.parse.quote_plus(query)
ivkremer

3
дуже добре, але чому не використовується Unicode? Якщо рядок URL-адреси є Unicode, я повинен кодувати його до UTF-8.Якщо це зробити?
Карл Доеніц

7
Це чудово працює, але я не зміг отримати доступ до деяких онлайн-сервісів (REST), поки не додав цей параметр safe = '; /?: @ & = + $,'
rovyko

Я спробував , що в Python 3 , але не зміг: stackoverflow.com/questions/40557606 / ...
amphibient

1
python3 -c "import urllib.parse, sys; print(urllib.parse.quote_plus(sys.argv[1])) "string to encode"для одного лайнера в командному рядку
Амос Джошуа

52

Спробуйте запити замість urllib і вам не потрібно турбуватися з urlencode!

import requests
requests.get('http://youraddress.com', params=evt.fields)

Редагувати:

Якщо вам потрібні впорядковані пари іменних пар або кілька значень для імені, тоді встановіть параметри так:

params=[('name1','value11'), ('name1','value12'), ('name2','value21'), ...]

замість використання словника.


5
Це не стосується питання впорядкування пар іменних значень, також для цього потрібен дозвіл на встановлення зовнішніх бібліотек, які можуть бути недоступними для проекту.
dreftymac

Я розмістив мінімальний код, який би працював для ОП. ОП не вимагає замовлених пар, проте це також можливо, див. Моє оновлення.
Барні

@dreftymac: це впорядкування адрес (хоча це не було частиною питання), будь ласка, прочитайте мою оновлену відповідь.
Барні

36

Контекст

  • Python (версія 2.7.2)

Проблема

  • Ви хочете генерувати рядок запиту, що кодується URL-адресою.
  • У вас є словник або об'єкт, що містить пари імені-значення.
  • Ви хочете мати можливість контролювати порядок виходів пар імен-значення.

Рішення

  • urllib.urlencode
  • urllib.quote_plus

Підводні камені

Приклад

Далі йде повне рішення, зокрема, як боротися з деякими підводними каменями.

### ********************
## init python (version 2.7.2 )
import urllib

### ********************
## first setup a dictionary of name-value pairs
dict_name_value_pairs = {
  "bravo"   : "True != False",
  "alpha"   : "http://www.example.com",
  "charlie" : "hello world",
  "delta"   : "1234567 !@#$%^&*",
  "echo"    : "user@example.com",
  }

### ********************
## setup an exact ordering for the name-value pairs
ary_ordered_names = []
ary_ordered_names.append('alpha')
ary_ordered_names.append('bravo')
ary_ordered_names.append('charlie')
ary_ordered_names.append('delta')
ary_ordered_names.append('echo')

### ********************
## show the output results
if('NO we DO NOT care about the ordering of name-value pairs'):
  queryString  = urllib.urlencode(dict_name_value_pairs)
  print queryString 
  """
  echo=user%40example.com&bravo=True+%21%3D+False&delta=1234567+%21%40%23%24%25%5E%26%2A&charlie=hello+world&alpha=http%3A%2F%2Fwww.example.com
  """

if('YES we DO care about the ordering of name-value pairs'):
  queryString  = "&".join( [ item+'='+urllib.quote_plus(dict_name_value_pairs[item]) for item in ary_ordered_names ] )
  print queryString
  """
  alpha=http%3A%2F%2Fwww.example.com&bravo=True+%21%3D+False&charlie=hello+world&delta=1234567+%21%40%23%24%25%5E%26%2A&echo=user%40example.com
  """ 


23

Спробуйте це:

urllib.pathname2url(stringToURLEncode)

urlencodeне працюватиме, оскільки працює лише зі словниками. quote_plusне дав правильний вихід.


Це справді корисно! У моєму випадку, у мене є тільки частина рядка , яку я хочу , щоб URL-кодування, наприклад , я хочу , щоб перетворити my stringв my%20string. Ваше рішення працює як шарм для цього!
TanguyP

Працював для мене, щоб отримати %20замість +. Спасибі
Йозеф Харуш

21

Зауважте, що urllib.urlencode не завжди робить трюк. Проблема полягає в тому, що деякі служби дбають про порядок аргументів, який втрачається під час створення словника. У таких випадках краще urllib.quote_plus, як запропонував Рікі.


2
Це добре працює і зберігає порядок, якщо ви передасте список кортежів:>>> import urllib >>> urllib.urlencode([('name', 'brandon'), ('uid', 1000)]) 'name=brandon&uid=1000'
Брендон Родос


6

для подальших посилань (наприклад: для python3)

>>> import urllib.request as req
>>> query = 'eventName=theEvent&eventDescription=testDesc'
>>> req.pathname2url(query)
>>> 'eventName%3DtheEvent%26eventDescription%3DtestDesc'

1
Зазвичай ви хочете лише
зашифрувати

Вихід для 'c:/2 < 3'Windows є '///C://2%20%3C%203'. Я хочу чогось, що тільки вийде 'c:/2%20%3C%203'.
бінкі

3

Для використання в скриптах / програмах, які повинні підтримувати і python 2, і 3, шість модулів надають функції цитування та urlencode:

>>> from six.moves.urllib.parse import urlencode, quote
>>> data = {'some': 'query', 'for': 'encoding'}
>>> urlencode(data)
'some=query&for=encoding'
>>> url = '/some/url/with spaces and %;!<>&'
>>> quote(url)
'/some/url/with%20spaces%20and%20%25%3B%21%3C%3E%26'

2

Якщо urllib.parse.urlencode () дає помилки, то спробуйте модуль urllib3.

Синтаксис виглядає наступним чином :

import urllib3
urllib3.request.urlencode({"user" : "john" }) 

1

Ще одна річ, про яку, можливо, вже не було сказано, це те urllib.urlencode(), що кодування порожніх значень у словнику буде як рядок Noneзамість відсутності цього параметра. Я не знаю, як правило, це бажано чи ні, але це не відповідає моєму випадку використання, отже, я повинен використовувати quote_plus.


0

Для того, що Python 3 urllib3 працює належним чином, ви можете використовувати наступне згідно з його офіційними документами :

import urllib3

http = urllib3.PoolManager()
response = http.request(
     'GET',
     'https://api.prylabs.net/eth/v1alpha1/beacon/attestations',
     fields={  # here fields are the query params
          'epoch': 1234,
          'pageSize': pageSize 
      } 
 )
response = attestations.data.decode('UTF-8')
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.