Jak urlencode kwerendę w Pythonie?


552

Próbuję urlencode ten ciąg przed przesłaniem.

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

Odpowiedzi:


561

Musisz przekazać swoje parametry urlencode()jako mapowanie (dict) lub sekwencję 2-krotek, takich jak:

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

Python 3 lub nowszy

Posługiwać się:

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

Zauważ, że ten sposób nie zrobić url kodowania w powszechnie używanych zmysł (spojrzenie na wyjściu). Do tego celu urllib.parse.quote_plus.


12
„Zauważ, że urllib.urlencode nie zawsze rozwiązuje problem. Problem polega na tym, że niektóre usługi dbają o kolejność argumentów, które gubią się podczas tworzenia słownika. W takich przypadkach lepiej jest urllib.quote_plus, jak sugerował Ricky. „
Blairg23,

16
Technicznie to błąd w usługach, prawda?
holdenweb,

5
i jak to zrobić, jeśli chcesz po prostu uczynić adres URL ciągu bezpiecznym, bez budowania pełnego ciągu argumentu zapytania?
Mike 'Pomax' Kamermans

1
@ Mike'Pomax'Kamermans - patrz np stackoverflow.com/questions/12082314/... lub odpowiedź Ricky'ego na to pytanie.
bporter

1
@ bk0 wygląda na to, że twoja metoda jest ważna tylko dla słowników, a nie ciągów.
JD Gamboa

1021

Python 2

To czego szukasz to 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'

Python 3

W Pythonie 3 urllibpakiet został podzielony na mniejsze komponenty. Użyjesz urllib.parse.quote_plus(zwróć uwagę na parsemoduł potomny)

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

4
Dzięki! W moim przypadku muszę jednak wprowadzić:import urllib.parse ... urllib.parse.quote_plus(query)
ivkremer

3
bardzo dobrze, ale dlaczego nie używał kodu Unicode? Jeśli ciąg adresu URL to Unicode, muszę go zakodować na UTF-8. Czy jest jakiś inny sposób?
Karl Doenitz

7
Działa to świetnie, ale nie mogłem uzyskać dostępu do niektórych usług online (REST), dopóki nie dodałem tego parametru safe = '; /?: @ & = + $,'
rovyko

Próbowałem tego w Pythonie 3, ale nie byłem w stanie: stackoverflow.com/questions/40557606/…
amfibia

1
python3 -c "import urllib.parse, sys; print(urllib.parse.quote_plus(sys.argv[1])) "string to encode"dla jednego linijki w wierszu poleceń
Amos Joshua

52

Wypróbuj żądania zamiast urllib i nie musisz przejmować się urlencode!

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

EDYTOWAĆ:

Jeśli potrzebujesz uporządkowanych par nazwa-wartość lub wielu wartości dla nazwy, ustaw następujące parametry:

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

zamiast używać słownika.


5
Nie rozwiązuje to problemu zamawiania par nazwa-wartość, wymaga to również pozwolenia na instalację zewnętrznych bibliotek, które mogą nie być wykonalne dla projektu.
dreftymac,

Opublikowałem minimalny kod, który działałby dla OP. OP nie zażądał zamówionych par, ale jest to również wykonalne, zobacz moją aktualizację.
Barney

@dreftymac: dotyczy to zamawiania (chociaż nie było to częścią pytania), przeczytaj moją zaktualizowaną odpowiedź.
Barney,

36

Kontekst

  • Python (wersja 2.7.2)

Problem

  • Chcesz wygenerować zakodowany ciąg zapytania.
  • Masz słownik lub obiekt zawierający pary nazwa-wartość.
  • Chcesz mieć możliwość kontrolowania kolejności wyjściowej par nazwa-wartość.

Rozwiązanie

  • urllib.urlencode
  • urllib.quote_plus

Pułapki

Przykład

Poniżej znajduje się kompletne rozwiązanie, w tym sposób radzenia sobie z niektórymi pułapkami.

### ********************
## 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

Spróbuj tego:

urllib.pathname2url(stringToURLEncode)

urlencodenie będzie działać, ponieważ działa tylko w słownikach. quote_plusnie wygenerował prawidłowego wyniku.


To bardzo pomocne! W moim przypadku, mam tylko część napisu, że chcę zakodować URL, na przykład chcę, aby przekształcić my stringsię my%20string. Twoje rozwiązanie działa jak urok!
TanguyP

Pracował dla mnie %20zamiast +. Dzięki
Jossef Harush

21

Zauważ, że urllib.urlencode nie zawsze załatwia sprawę. Problem polega na tym, że niektóre usługi dbają o kolejność argumentów, które gubią się podczas tworzenia słownika. W takich przypadkach lepiej jest urllib.quote_plus, jak sugerował Ricky.


2
Działa dobrze i zachowuje porządek, jeśli przejdziesz listę krotek:>>> import urllib >>> urllib.urlencode([('name', 'brandon'), ('uid', 1000)]) 'name=brandon&uid=1000'
Brandon Rhodes

8

W Pythonie 3 to zadziałało ze mną

import urllib

urllib.parse.quote(query)

6

dla przyszłych odniesień (np .: dla python3)

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

1
zazwyczaj chcesz tylko zakodować adresy URL, to, co tu zrobiłeś, spowodowałoby nieprawidłowe zapytanie GET
Codewithcheese

Dane wyjściowe dla 'c:/2 < 3'systemu Windows to '///C://2%20%3C%203'. Chcę czegoś, co po prostu wyjdzie 'c:/2%20%3C%203'.
binki

3

Do użytku w skryptach / programach, które muszą obsługiwać zarówno Python 2, jak i 3, moduł sześciu udostępnia funkcje cytowania i 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

Jeśli funkcja urllib.parse.urlencode () powoduje błędy, wypróbuj moduł urllib3.

Składnia jest następująca:

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

1

Inną rzeczą, o której jeszcze nie wspomniano, jest urllib.urlencode()zakodowanie pustych wartości w słowniku jako ciągu Nonezamiast braku tego parametru. Nie wiem, czy jest to zwykle pożądane, czy nie, ale nie pasuje do mojego przypadku użycia, dlatego muszę go użyć quote_plus.


0

Dla urllib3 w Pythonie 3 działa poprawnie, możesz użyć następujących instrukcji zgodnie z oficjalnymi dokumentami :

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')
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.