Wie kann man einen Querystring in Python urlencodieren?

552

Ich versuche, diese Zeichenfolge vor dem Senden zu urlencodieren.

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

Antworten:

561

Sie müssen Ihre Parameter urlencode()entweder als Mapping (Diktat) oder als Folge von 2-Tupeln übergeben, z.

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

Python 3 oder höher

Verwenden:

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

Beachten Sie, dass dies nicht nicht url tun kodiert , in dem üblicherweise verwendeten Sinne (Blick auf der Ausgabe). Für diesen Gebrauch urllib.parse.quote_plus.

bgporter
quelle
12
"Beachten Sie, dass der urllib.urlencode nicht immer den Trick macht. Das Problem ist, dass einige Dienste sich um die Reihenfolge der Argumente kümmern, die beim Erstellen des Wörterbuchs verloren gehen. In solchen Fällen ist urllib.quote_plus besser, wie Ricky vorgeschlagen hat. ""
Blairg23
16
Technisch gesehen ist das ein Fehler in den Diensten, nicht wahr?
Holdenweb
5
und wie würde man das tun, wenn man nur eine String-URL sicher machen möchte, ohne eine vollständige String-Abfrage-Argument-String zu erstellen?
Mike 'Pomax' Kamermans
1
@ Mike'Pomax'Kamermans - siehe z. B. stackoverflow.com/questions/12082314/… oder Rickys Antwort auf diese Frage.
Bgporter
1
@ bk0 Ihre Methode scheint nur für Wörterbücher und nicht für Zeichenfolgen gültig zu sein.
JD Gamboa
1021

Python 2

Was Sie suchen ist 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

In Python 3 wurde das urllibPaket in kleinere Komponenten aufgeteilt. Sie verwenden urllib.parse.quote_plus(beachten Sie das parseuntergeordnete Modul)

import urllib.parse
urllib.parse.quote_plus(...)
Ricky
quelle
4
Vielen Dank! In meinem Fall muss ich jedoch setzen:import urllib.parse ... urllib.parse.quote_plus(query)
ivkremer
3
Sehr gut, aber warum nicht Unicode verwendet? Wenn die URL-Zeichenfolge Unicode ist, muss ich sie in UTF-8 codieren. Gibt es eine andere Möglichkeit, dies zu tun?
Karl Dönitz
7
Dies funktioniert hervorragend, aber ich konnte nicht auf einige Onlinedienste (REST) ​​zugreifen, bis ich diesen Parameter safe = '; / ?: @ & = + $,'
rovyko
Ich habe versucht , dass in Python 3 , aber war nicht in der Lage zu: stackoverflow.com/questions/40557606/...
amphibient
1
python3 -c "import urllib.parse, sys; print(urllib.parse.quote_plus(sys.argv[1])) "string to encode"für einen Einzeiler auf der Kommandozeile
Amos Joshua
52

Probieren Sie Anfragen anstelle von urllib aus und Sie müssen sich nicht um urlencode kümmern!

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

BEARBEITEN:

Wenn Sie geordnete Name-Wert-Paare oder mehrere Werte für einen Namen benötigen, legen Sie folgende Parameter fest:

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

anstatt ein Wörterbuch zu verwenden.

Barney
quelle
5
Dies behebt nicht das Problem der Bestellung der Name-Wert-Paare. Außerdem ist die Berechtigung zum Installieren externer Bibliotheken erforderlich, die für das Projekt möglicherweise nicht möglich sind.
Dreftymac
Ich habe den minimalen Code gepostet, der für das OP funktionieren würde. Das OP hat keine bestellten Paare angefordert, aber es ist auch machbar, siehe mein Update.
Barney
@dreftymac: Dies betrifft die Bestellung von Adressen (obwohl dies nicht Teil der Frage war). Bitte lesen Sie meine aktualisierte Antwort.
Barney
36

Kontext

  • Python (Version 2.7.2)

Problem

  • Sie möchten eine urlencodierte Abfragezeichenfolge generieren.
  • Sie haben ein Wörterbuch oder Objekt, das die Name-Wert-Paare enthält.
  • Sie möchten die Ausgabereihenfolge der Name-Wert-Paare steuern können.

Lösung

  • urllib.urlencode
  • urllib.quote_plus

Tücken

Beispiel

Das Folgende ist eine vollständige Lösung, einschließlich des Umgangs mit einigen Fallstricken.

### ********************
## 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"    : "[email protected]",
  }

### ********************
## 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
  """ 
dreftymac
quelle
23

Versuche dies:

urllib.pathname2url(stringToURLEncode)

urlencodefunktioniert nicht, weil es nur in Wörterbüchern funktioniert. quote_plushat nicht die richtige Ausgabe erzeugt.

Charlie
quelle
Das ist wirklich hilfreich! In meinem Fall habe ich nur einen Teil der Zeichenfolge, die ich zu URL-kodieren möchten, zum Beispiel ich transformieren möchten my stringzu my%20string. Ihre Lösung funktioniert wie ein Zauber dafür!
TanguyP
Arbeitete für mich zu bekommen %20statt +. Vielen Dank
Jossef Harush
21

Beachten Sie, dass der urllib.urlencode nicht immer den Trick macht. Das Problem ist, dass sich einige Dienste um die Reihenfolge der Argumente kümmern, die beim Erstellen des Wörterbuchs verloren gehen. In solchen Fällen ist urllib.quote_plus besser, wie Ricky vorgeschlagen hat.

user411279
quelle
2
Es funktioniert gut und bewahrt die Ordnung, wenn Sie eine Liste von Tupeln übergeben:>>> import urllib >>> urllib.urlencode([('name', 'brandon'), ('uid', 1000)]) 'name=brandon&uid=1000'
Brandon Rhodes
8

In Python 3 hat das bei mir funktioniert

import urllib

urllib.parse.quote(query)
Mazen Aly
quelle
6

für zukünftige Referenzen (zB für python3)

>>> import urllib.request as req
>>> query = 'eventName=theEvent&eventDescription=testDesc'
>>> req.pathname2url(query)
>>> 'eventName%3DtheEvent%26eventDescription%3DtestDesc'
Nickanor
quelle
1
Normalerweise möchten Sie nur die Werte
per
Die Ausgabe für 'c:/2 < 3'unter Windows ist '///C://2%20%3C%203'. Ich möchte etwas, das nur ausgegeben wird 'c:/2%20%3C%203'.
Binki
3

Für die Verwendung in Skripten / Programmen, die sowohl Python 2 als auch Python 3 unterstützen müssen, bietet das Sechs-Modul Anführungszeichen- und Urlencode-Funktionen:

>>> 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'
bschlueter
quelle
2

Wenn der urllib.parse.urlencode () Fehler anzeigt, probieren Sie das urllib3-Modul aus.

Die Syntax lautet wie folgt:

import urllib3
urllib3.request.urlencode({"user" : "john" }) 
Natesh bhat
quelle
1

Eine andere Sache, die möglicherweise noch nicht erwähnt wurde, ist, dass urllib.urlencode()leere Werte im Wörterbuch als Zeichenfolge codiert werden, Noneanstatt dass dieser Parameter nicht vorhanden ist. Ich weiß nicht, ob dies normalerweise erwünscht ist oder nicht, passt aber nicht zu meinem Anwendungsfall, daher muss ich es verwenden quote_plus.

Joseph
quelle
0

Für Python 3 funktioniert urllib3 ordnungsgemäß. Sie können Folgendes gemäß den offiziellen Dokumenten verwenden :

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')
cryptoKTM
quelle