2012-05-26 11 views
6

Ich versuche, eine URL zu erstellen, so dass ich eine Anfrage senden kann, die urllib Modul verwendet.Abfragezeichenfolge mit urlencode python erstellen

Lassen Sie uns meine final_url nehme

url = "www.example.com/find.php?data=http%3A%2F%2Fwww.stackoverflow.com&search=Generate+value" 

Nun, dies zu erreichen sein sollte ich die folgende Art und Weise versucht:

>>> 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' 

Jetzt können Sie Beobachter zwei Dinge, wenn Sie meine query_string mit dem Format von final_url vergleichen

1) Die Reihenfolge der Parameter ist umgekehrt data=()&search= es ist search=()&data=

2) urlencode codiert auch die + in Generate+value

Ich glaube, die erste Änderung des zufälligen Verhaltens Wörterbuch zurückzuführen ist. Also, ich benutze OrderedDict to reverse the dictionary. Wie ich python 2.6.5 verwende habe ich

pip install ordereddict 

Aber ich bin nicht in der Lage es in meinem Code zu verwenden, wenn ich

>>> od = OrderedDict((('a', 'first'), ('b', 'second'))) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'OrderedDict' is not defined 

So versuche, meine Frage ist, was ist der richtige Weg OrderedDict zu verwenden, in Python 2.6.5 und wie mache ich urlencode ignoriert die + in Generate+value.

Auch ist dies der richtige Ansatz, URL zu bauen.

Antwort

15

Sie sollten sich keine Sorgen über die Kodierung + machen, die auf dem Server wiederhergestellt werden soll, nachdem die URL entfernt wurde. Die Reihenfolge der benannten Parameter sollte ebenfalls keine Rolle spielen.

Anbetracht OrderedDict ist es nicht Python eingebaut Sie sollten es importieren aus 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)) 

wenn Ihr Python zu alt ist und nicht über OrderedDict im Modul collections, Verwendung:

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

Wie auch immer, die Reihenfolge der Parameter sollte keine Rolle spielen.

Beachten Sie den Parameter safe von quote. Es verhindert, dass + maskiert wird, aber es bedeutet, dass der Server Generate+value als Generate value interpretiert. Sie können manuell + entkommen, indem %2B und Kennzeichnung % als sicher char schreiben:

+0

Ich versuchte 'von Sammlungen importieren OrderedDict', aber jetzt bekomme ich' ImportError: kann Name OrderedDict' nicht importieren. Ich benutze Python '2.6.5' – RanRag

+0

Es sollte von PYTON 2.4 zur Verfügung stehen. Was bekommen Sie, wenn Sie 'Importsammlungen' ausführen? –

+0

Ich kann die Sammlung erfolgreich importieren, es wird kein Fehler ausgegeben. Ich habe 'OrderedDict' von Python 2.7 an eingeführt. – RanRag

3

Zunächst wird die Reihenfolge der Parameter in einer HTTP-Anforderung sollte völlig irrelevant sein. Wenn dies nicht der Fall ist, macht die Parsing-Bibliothek auf der anderen Seite etwas falsch.

Zweitens ist natürlich die + codiert. + wird als Platzhalter für ein Leerzeichen in einer codierten URL verwendet. Wenn yor oder row eine + enthält, muss dies maskiert werden.urlencode erwartet eine nicht kodierte Zeichenkette. Sie können eine Zeichenkette, die bereits kodiert ist, nicht übergeben.

+0

Danke, dass Sie Recht haben. Ich habe nicht nachgesehen, bevor ich nach meinem Fehler gefragt habe. – RanRag

0

Einige Bemerkungen über die Frage und andere Antworten:

  1. Wenn Sie Auftrag mit urllib.urlencode erhalten wollen, senden eine geordnete Folge von k/v Paare statt Mapping (dict). Wenn Sie ein Diktat übergeben, ruft urlencode einfach foo.items() an, um eine iterierbare Sequenz zu erhalten.

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

Sie auch in einem secondard doseq Argument übergeben können einstellen, wie iterable Werte behandelt werden.

  1. Die Reihenfolge der Parameter ist nicht irrelevant. nimm diese beiden Urls zum Beispiel:

    https://example.com?foo=bar&bar=foo https://example.com?bar=foo&foo=bar

    Ein HTTP-Server irrelevant die Reihenfolge dieser Parameter in Betracht ziehen sollte, sondern eine Funktion entwickelt, URLs würde vergleichen nicht. Um URLs sicher zu vergleichen, müssten diese Parameter sortiert werden.

    Allerdings betrachten Nachschlüssel:

    https://example.com?foo=3&foo=2&foo=1

Die URI Spezifikationen Nachschlüssel unterstützen, aber nicht Vorrang oder Bestelladresse.

in einer bestimmten Anwendung, diese könnte jedes auslösen unterschiedliche Ergebnisse und auch gültig sein:

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. Die + ist ein reserviertes Zeichen, die einen Raum in einer urlencoded Form darstellt (vs %20 zum Teil der Weg). urllib.urlencode Escapezeichen mit urllib.quote_plus(), nicht urllib.quote(). Die OP höchstwahrscheinlich wollte nur dies tun:

initial_url = "http://www.stackoverflow.com" search = "Generate value" urllib.urlencode((("data", initial_url), ("search", search)))

Welche produziert:

data=http%3A%2F%2Fwww.stackoverflow.com&search=Generate+value

als Ausgang.

Verwandte Themen