Wie ein urlencoded Unicode-String in Python unquote?
-
08-07-2019 - |
Frage
Ich habe einen Unicode-String wie "Tanım", die als "Tan% u0131m" irgendwie codiert ist. Wie kann ich konvertieren diese kodierten String zurück zur ursprünglichen Unicode. Offenbar hat urllib.unquote nicht Unicode-Unterstützung.
Lösung
% uXXXX ist ein Nicht-Standard-Kodierungsschema das gewesen ist abgelehnt von der w3c, trotz der Tatsache, dass eine Implementierung in JavaScript Land leben weiter.
Die üblichere Technik scheint die Zeichenfolge in UTF-8 zu sein, und dann zu entkommen% der resultierenden Bytes mit% XX. Dieses Schema wird durch urllib.unquote unterstützt:
>>> urllib2.unquote("%0a")
'\n'
Leider, wenn Sie wirklich Notwendigkeit % uXXXX unterstützen, werden Sie wahrscheinlich Ihre eigenen Decoder rollen. Ansonsten ist es wahrscheinlich weit mehr vorzuziehen, einfach UTF-8 kodieren Ihre Unicode und dann% entkommen die resultierenden Bytes sein.
Ein vollständigeres Beispiel:
>>> u"Tanım"
u'Tan\u0131m'
>>> url = urllib.quote(u"Tanım".encode('utf8'))
>>> urllib.unquote(url).decode('utf8')
u'Tan\u0131m'
Andere Tipps
def unquote(text):
def unicode_unquoter(match):
return unichr(int(match.group(1),16))
return re.sub(r'%u([0-9a-fA-F]{4})',unicode_unquoter,text)
Dies wird es tun, wenn Sie unbedingt diese haben (ich wirklich mit den Schreien von „non-standard“ stimmen):
from urllib import unquote
def unquote_u(source):
result = unquote(source)
if '%u' in result:
result = result.replace('%u','\\u').decode('unicode_escape')
return result
print unquote_u('Tan%u0131m')
> Tanım
es ist ein Fehler in der obigen Version ist, wo es manchmal flippt aus, wenn es sowohl ASCII-Code und Unicode-codierte Zeichen in der Zeichenkette. Ich denke, die speziell wenn es Zeichen aus dem oberen 128 Bereich wie ‚\ xab‘ zusätzlich zu Unicode.
zB. "% 5B% AB% u03E1% BB% 5D" verursacht diesen Fehler.
Ich fand, wenn man nur die Unicode diejenigen zuerst tat, ging das Problem weg:
def unquote_u(source):
result = source
if '%u' in result:
result = result.replace('%u','\\u').decode('unicode_escape')
result = unquote(result)
return result
Sie haben eine URL ein Nicht-Standard-Kodierungsschema von Normungsgremien abgelehnt, aber immer noch von einigem Encoder erzeugt werden. Die Funktion Python urllib.parse.unquote()
können diese nicht verarbeiten.
Ihre eigenen Decoder zu schaffen, ist nicht so schwer, zum Glück. %uhhhh
Einträge sollen sein UTF-16 Codepoints hier, also müssen wir nehmen Ersatzpaar berücksichtigt. Ich habe auch %hh
Codepoints gemischt, für zusätzliche Verwirrung.
, die mit im Auge, hier ist ein Decoder, der sowohl in Python 2 und Python funktioniert 3, vorausgesetzt, übergeben Sie in einem str
Objekt in Python 3 (Python 2 Sorgen weniger):
try:
# Python 3
from urllib.parse import unquote
unichr = chr
except ImportError:
# Python 2
from urllib import unquote
def unquote_unicode(string, _cache={}):
string = unquote(string) # handle two-digit %hh components first
parts = string.split(u'%u')
if len(parts) == 1:
return parts
r = [parts[0]]
append = r.append
for part in parts[1:]:
try:
digits = part[:4].lower()
if len(digits) < 4:
raise ValueError
ch = _cache.get(digits)
if ch is None:
ch = _cache[digits] = unichr(int(digits, 16))
if (
not r[-1] and
u'\uDC00' <= ch <= u'\uDFFF' and
u'\uD800' <= r[-2] <= u'\uDBFF'
):
# UTF-16 surrogate pair, replace with single non-BMP codepoint
r[-2] = (r[-2] + ch).encode(
'utf-16', 'surrogatepass').decode('utf-16')
else:
append(ch)
append(part[4:])
except ValueError:
append(u'%u')
append(part)
return u''.join(r)
Die Funktion wird stark von der aktuelle Standard-Bibliothek Implementierung .
Demo:
>>> print(unquote_unicode('Tan%u0131m'))
Tanım
>>> print(unquote_unicode('%u05D0%u05D9%u05DA%20%u05DE%u05DE%u05D9%u05E8%u05D9%u05DD%20%u05D0%u05EA%20%u05D4%u05D8%u05E7%u05E1%u05D8%20%u05D4%u05D6%u05D4'))
איך ממירים את הטקסט הזה
>>> print(unquote_unicode('%ud83c%udfd6')) # surrogate pair
🏖
>>> print(unquote_unicode('%ufoobar%u666')) # incomplete
%ufoobar%u666
Die Funktion auf Python arbeitet 2 (getestet auf 2,4-2,7) und Python 3 (getestet auf 3,3-3,8).