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.