python - emoji中文 - unicode emoji table




從Unicode字符串中正確提取Emojis (2)

我會使用uniseg庫( pip install uniseg ):

# -*- coding: utf-8 -*-
from uniseg import graphemecluster as gc

print list(gc.grapheme_clusters(u'😘😘xyz😊😊'))

輸出[u'\U0001f618', u'\U0001f618', u'x', u'y', u'z', u'\U0001f60a', u'\U0001f60a']

[x.encode('utf-8') for x in gc.grapheme_clusters(u'😘😘xyz😊😊'))]

將提供字符列表作為UTF-8編碼的字符串。

我在Python 2中工作,我有一個包含emojis以及其他Unicode字符的字符串。 我需要將其轉換為列表中的每個條目是單個字符/表情符號的列表。

x = u'😘😘xyz😊😊'
char_list = [c for c in x]

期望的輸出是:

['😘', '😘', 'x', 'y', 'z', '😊', '😊']

實際產出是:

[u'\ud83d', u'\ude18', u'\ud83d', u'\ude18', u'x', u'y', u'z', u'\ud83d', u'\ude0a', u'\ud83d', u'\ude0a']

我怎樣才能達到理想的輸出?


首先,在Python2中,需要使用Unicode字符串( u'<...>' )來表示Unicode字符。 如果您想使用字符而不是源代碼中的\UXXXXXXXX表示,請使用正確的源編碼

現在,根據Python:當它包含代理對Python時返回 正確的字符串長度 為單個Unicode字符串返回長度為2 ,在Python2“窄”生成(與sys.maxunicode==65535 ),表示32位Unicode字符作為代理對 ,這對字符串函數是不透明的。 這只是在3.3( PEP0393 )中確定的。

最簡單的解決方案(除了遷移到3.3+以外)是從第三方鏈接中概述的源代碼編譯一個Python“寬”的構建。 其中,Unicode字符都是4字節(因此是一個潛在的內存豬),但如果你需要經常處理寬Unicode字符,這可能是一個可以接受的價格。

“窄”構建的解決方案製作一組自定義的字符串函數lenslice ;也許作為unicode的子類),它將檢測代理對並將它們作為單個字符處理。 我很難找到一個現成的(這很奇怪),但是寫起來並不難:

  • 按照UTF-16#U + 10000到U + 10FFFF - 維基百科
    • 第一個字符(高代理)的範圍是0xD800..0xDBFF
    • 第二個字符(低代理) - 範圍0xDC00..0xDFFF
    • 這些範圍是保留的,因此不能作為常規字符出現

所以這裡是檢測代理對的代碼:

def is_surrogate(s,i):
    if 0xD800 <= ord(s[i]) <= 0xDBFF:
        try:
            l = s[i+1]
        except IndexError:
            return False
        if 0xDC00 <= ord(l) <= 0xDFFF:
            return True
        else:
            raise ValueError("Illegal UTF-16 sequence: %r" % s[i:i+2])
    else:
        return False

而一個函數返回一個簡單的片:

def slice(s,start,end):
    l=len(s)
    i=0
    while i<start and i<l:
        if is_surrogate(s,i):
            start+=1
            end+=1
            i+=1
        i+=1
    while i<end and i<l:
        if is_surrogate(s,i):
            end+=1
            i+=1
        i+=1
    return s[start:end]

在這裡,你付出的代價是性能,因為這些函數比內置函數慢得多:

>>> ux=u"a"*5000+u"\U00100000"*30000+u"b"*50000
>>> timeit.timeit('slice(ux,10000,100000)','from __main__ import slice,ux',number=1000)
46.44128203392029    #msec
>>> timeit.timeit('ux[10000:100000]','from __main__ import slice,ux',number=1000000)
8.814016103744507    #usec






emoji