391 Stimmen

Url entschlüsseln UTF-8 in Python

In Python 2.7, wenn eine URL wie example.com?title=%D0%BF%D1%80%D0%B0%D0%B2%D0%BE%D0%B2%D0%B0%D1%8F+%D0%B7%D0%B0%D1%89%D0%B8%D1%82%D0%B0 gegeben ist, wie kann ich sie zum erwarteten Ergebnis example.com?title==+ dekodieren?

Ich habe url=urllib.unquote(url.encode("utf8")) versucht, aber anscheinend liefert es ein falsches Ergebnis.

622voto

Martijn Pieters Punkte 953257

Die Daten sind UTF-8-codierte Bytes, die mit URL-Zitierungen maskiert sind, daher müssen Sie sie mit decodieren, mit urllib.parse.unquote(), das die Decodierung von prozentcodierten Daten in UTF-8-Bytes und dann in Text transparent durchführt:

from urllib.parse import unquote

url = unquote(url)

Demo:

>>> from urllib.parse import unquote
>>> url = 'example.com?title=%D0%BF%D1%80%D0%B0%D0%B2%D0%BE%D0%B2%D0%B0%D1%8F+%D0%B7%D0%B0%D1%89%D0%B8%D1%82%D0%B0'
>>> unquote(url)
'example.com?title=+'

Das Äquivalent in Python 2 ist urllib.unquote(), aber dies liefert eine Bytestring zurück, daher müssten Sie manuell dekodieren:

from urllib import unquote

url = unquote(url).decode('utf8')

164voto

pavan Punkte 3095

Wenn Sie Python 3 verwenden, können Sie urllib.parse.unquote verwenden:

url = """example.com?title=%D0%BF%D1%80%D0%B0%D0%B2%D0%BE%D0%B2%D0%B0%D1%8F+%D0%B7%D0%B0%D1%89%D0%B8%D1%82%D0%B0"""

import urllib.parse
urllib.parse.unquote(url)

ergibt:

'example.com?title=+'

26voto

ivanleoncz Punkte 7119

Sie können auch ein erwartetes Ergebnis mit der requests-Bibliothek erzielen:

import requests

url = "http://www.meinewebsite.de/Daten%20Set.zip"

print(f"Vorher: {url}")
print(f"Nachher:  {requests.utils.unquote(url)}")

Ausgabe:

$ python3 test_url_unquote.py

Vorher: http://www.meinewebsite.de/Daten%20Set.zip
Nachher:  http://www.meinewebsite.de/Daten Set.zip

Könnte nützlich sein, wenn Sie bereits requests verwenden, ohne eine andere Bibliothek für diese Aufgabe zu verwenden.

2voto

Roland Puntaier Punkte 2889

In HTML können URLs html-entitäten enthalten. das ersetzt sie auch.

#from urllib import unquote #earlier python version
from urllib.request import unquote
from html import unescape
unescape(unquote('https://v.w.xy/p1/p22?userId=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&confirmationToken=7uAf%2fxJoxRTFAZdxslCn2uwVR9vV7cYrlHs%2fl9sU%2frix9f9CnVx8uUT%2bu8y1%2fWCs99INKDnfA2ayhGP1ZD0z%2bodXjK9xL5I4gjKR2xp7p8Sckvb04mddf%2fiG75QYiRevgqdMnvd9N5VZp2ksBc83lDg7%2fgxqIwktteSI9RA3Ux9VIiNxx%2fZLe9dZSHxRq9AA'))

2voto

Ich weiß, das ist eine alte Frage, aber ich bin über sie bei der Google-Suche gestolpert und habe festgestellt, dass niemand eine Lösung nur mit eingebauten Features vorgeschlagen hat.

Also habe ich schnell meine eigene geschrieben.

Grundsätzlich kann eine URL-Zeichenkette nur diese Zeichen enthalten: A-Z, a-z, 0-9, -, ., _, ~, :, /, ?, #, [, ], @, !, $, &, ', (, ), *, +, ,, ;, % und =, alles andere wird URL-codiert.

URL-Codierung ist ziemlich geradlinig, einfach ein Prozentzeichen gefolgt von den hexadezimalen Ziffern der Byte-Werte, die den Codepunkten von ungültigen Zeichen entsprechen.

Also im Grunde genommen sollte es perfekt funktionieren, indem man eine einfache while-Schleife benutzt, um die Zeichen zu durchlaufen, fügt man jedes Byte als solches hinzu, wenn es kein Prozentzeichen ist, erhöht man den Index um eins. Andernfalls fügt man das Byte nach dem Prozentzeichen hinzu und erhöht den Index um drei, akkumuliert die Bytes und das Dekodieren sollte perfekt funktionieren.

Hier ist der Code:

def url_parse(url):
    l = len(url)
    data = bytearray()
    i = 0
    while i < l:
        if url[i] != '%':
            d = ord(url[i])
            i += 1

        else:
            d = int(url[i+1:i+3], 16)
            i += 3

        data.append(d)

    return data.decode('utf8')

Ich habe es getestet und es funktioniert perfekt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X