Como unquote uma string unicode urlencoded em python?

votos
40

Eu tenho um string unicode como Tanım, que é codificado como Tan% u0131m de alguma forma. Como posso converter essa string codificada de volta para unicode originais. Aparentemente urllib.unquote não suporta unicode.

Publicado 18/11/2008 em 23:49
fonte usuário
Em outras línguas...                            


5 respostas

votos
9
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)
Respondeu 19/11/2008 em 00:22
fonte usuário

votos
63

% uXXXX é um esquema de codificação não-padrão que tenha sido rejeitado pelo W3C, apesar do fato de que uma implementação continua a viver na terra JavaScript.

A técnica mais comum parece ser a UTF-8 codifica a cadeia e, em seguida,% escapar os bytes resultantes, utilizando% XX. Este esquema é suportado por urllib.unquote:

>>> urllib2.unquote("%0a")
'\n'

Infelizmente, se você realmente precisa para apoiar% uXXXX, provavelmente você vai ter que rolar o seu próprio decodificador. Caso contrário, é provável que seja muito mais preferível simplesmente UTF-8 codificar o Unicode e, em seguida,% escapar os bytes resultantes.

Um exemplo mais completo:

>>> u"Tanım"
u'Tan\u0131m'
>>> url = urllib.quote(u"Tanım".encode('utf8'))
>>> urllib.unquote(url).decode('utf8')
u'Tan\u0131m'
Respondeu 19/11/2008 em 00:22
fonte usuário

votos
6

Isso vai fazê-lo se você absolutamente tem que ter isso (Eu realmente concordo com os gritos de "não-padrão"):

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
Respondeu 19/11/2008 em 00:32
fonte usuário

votos
4

há um bug na versão acima, onde se assusta às vezes, quando há tanto ascii codificado e unicode codificado caracteres na cadeia. Eu acho que é especificamente quando há personagens do 128 intervalo superior como '\ xab', além de unicode.

por exemplo. "% 5B% AB% u03E1% BB% 5D" causa esse erro.

Descobri que se você acabou de fazer os unicode em primeiro lugar, o problema foi embora:

def unquote_u(source):
  result = source
  if '%u' in result:
    result = result.replace('%u','\\u').decode('unicode_escape')
  result = unquote(result)
  return result
Respondeu 16/12/2008 em 04:13
fonte usuário

votos
0

Você tem um URL usando um esquema de codificação não-padrão , rejeitada pelos organismos de normalização, mas ainda está sendo produzido por alguns codificadores. O Python urllib.parse.unquote()função não pode lidar com estes.

Criar o seu próprio decodificador não é tão difícil, felizmente. %uhhhhentradas são destinadas a ser UTF-16 codepoints aqui, então precisamos tomar pares substitutos em conta. Eu também vi %hhcodepoints misturados, para a confusão acrescentou.

Com isso em mente, aqui é um decodificador que funciona tanto em Python 2 e Python 3, desde que você passar em um strobjeto em Python 3 (Python 2 cuidados 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)

A função é fortemente inspirado pela implementação padrão da biblioteca atual .

demonstração:

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

A função funciona em Python 2 (testado em 2,4-2,7) e Python 3 (testado em 3,3-3,8).

Respondeu 07/03/2019 em 14:41
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more