10

这里给出的答案:如何在 Python 中使用代理对?告诉您如何将代理对转换'\ud83d\ude4f'为单个非 BMP unicode 字符(答案是"\ud83d\ude4f".encode('utf-16', 'surrogatepass').decode('utf-16'))。我想知道如何反向执行此操作。我如何使用 Python 从非 BMP 字符中找到等效的代理对,将'\U0001f64f'() 转换回'\ud83d\ude4f'. 我找不到明确的答案。

4

2 回答 2

5

您必须手动将每个非 BMP 点替换为代理对。您可以使用正则表达式执行此操作:

import re

_nonbmp = re.compile(r'[\U00010000-\U0010FFFF]')

def _surrogatepair(match):
    char = match.group()
    assert ord(char) > 0xffff
    encoded = char.encode('utf-16-le')
    return (
        chr(int.from_bytes(encoded[:2], 'little')) + 
        chr(int.from_bytes(encoded[2:], 'little')))

def with_surrogates(text):
    return _nonbmp.sub(_surrogatepair, text)

演示:

>>> with_surrogates('\U0001f64f')
'\ud83d\ude4f'
于 2016-10-24T16:28:32.757 回答
3

这有点复杂,但这里有一个单行来转换单个字符:

>>> emoji = '\U0001f64f'
>>> ''.join(chr(x) for x in struct.unpack('>2H', emoji.encode('utf-16be')))
'\ud83d\ude4f'

要转换混合字符,需要将该表达式与另一个包围:

>>> emoji_str = 'Here is a non-BMP character: \U0001f64f'
>>> ''.join(c if c <= '\uffff' else ''.join(chr(x) for x in struct.unpack('>2H', c.encode('utf-16be'))) for c in emoji_str)
'Here is a non-BMP character: \ud83d\ude4f'
于 2016-10-24T17:23:36.693 回答