¿Cómo poner entre comillas una cadena Unicode codificada en Python?
-
08-07-2019 - |
Pregunta
Tengo una cadena unicode como '' Tanim '' que está codificado como " Tan% u0131m " de algun modo. ¿Cómo puedo convertir esta cadena codificada de nuevo a Unicode original? Aparentemente, urllib.unquote no es compatible con Unicode.
Solución
% uXXXX es un esquema de codificación no estándar que ha sido rechazado por el w3c, a pesar del hecho de que una implementación continúa viviendo en JavaScript.
La técnica más común parece ser UTF-8 codificar la cadena y luego% escapar de los bytes resultantes usando% XX. Este esquema es compatible con urllib.unquote:
>>> urllib2.unquote("%0a")
'\n'
Desafortunadamente, si realmente necesita para admitir% uXXXX, probablemente tendrá que rodar su propio decodificador. De lo contrario, es probable que sea mucho más preferible simplemente codificar UTF-8 en su Unicode y luego% escapar de los bytes resultantes.
Un ejemplo más completo:
>>> u"Tanım"
u'Tan\u0131m'
>>> url = urllib.quote(u"Tanım".encode('utf8'))
>>> urllib.unquote(url).decode('utf8')
u'Tan\u0131m'
Otros consejos
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)
Esto lo hará si absolutamente tiene que tener esto (realmente estoy de acuerdo con los gritos de "no estándar"):
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
hay un error en la versión anterior donde a veces se asusta cuando hay caracteres codificados con ASCII y codificados con Unicode en la cadena. Creo que es específicamente cuando hay caracteres del rango superior de 128 como '\ xab' además de Unicode.
ej. "% 5B% AB% u03E1% BB% 5D " causa este error.
Descubrí que si primero hiciste los Unicode, el problema desapareció:
def unquote_u(source):
result = source
if '%u' in result:
result = result.replace('%u','\\u').decode('unicode_escape')
result = unquote(result)
return result
Tiene una URL que utiliza un esquema de codificación no estándar , rechazado por los organismos de normalización pero aún siendo producido por algunos codificadores. La función Python urllib.parse.unquote ()
no puede manejarlos.
Crear su propio decodificador no es tan difícil, afortunadamente. Las entradas % uhhhh
están destinadas a ser UTF-16 puntos de código aquí, por lo que debemos tomar pares sustitutos en cuenta. También he visto % hh
puntos de código mezclados, para mayor confusión.
Con eso en mente, aquí hay un decodificador que funciona tanto en Python 2 como en Python 3, siempre que pase un objeto str
en Python 3 (Python 2 se preocupa menos):
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)
La función está fuertemente inspirada en