从多语言Unicode文本中删除表情符号

时间:2018-08-10 10:56:10

标签: python regex string unicode emoji

我正在尝试从Unicode文本中删除 just 表情符号。我尝试了各种方法described in another Stack Overflow post,但是这些方法都没有完全删除所有表情符号/笑脸。例如:

解决方案1:

def remove_emoji(self, string):
    emoji_pattern = re.compile("["
                           u"\U0001F600-\U0001F64F"  # emoticons
                           u"\U0001F300-\U0001F5FF"  # symbols & pictographs
                           u"\U0001F680-\U0001F6FF"  # transport & map symbols
                           u"\U0001F1E0-\U0001F1FF"  # flags (iOS)
                           u"\U00002702-\U000027B0"
                           u"\U000024C2-\U0001F251"
                           "]+", flags=re.UNICODE)
    return emoji_pattern.sub(r'', string)

留在以下示例中:

Input: తెలంగాణ రియల్ ఎస్టేట్ 
Output: తెలంగాణ రియల్ ఎస్టేట్ 

另一种尝试,解决方案2:

def deEmojify(self, inputString):
    returnString = ""
    for character in inputString:
        try:
            character.encode("ascii")
            returnString += character
        except UnicodeEncodeError:
            returnString += ''
    return returnString

删除所有非英语字符的结果:

 Input: Testరియల్ ఎస్టేట్ A.P&T.S. 
 Output: Test  A.P&T.S. 

由于character.encode("ascii"),它不仅删除了所有表情符号,而且还删除了非英文字符;我的非英语输入无法编码为ASCII。

有什么方法可以从国际Unicode文本中正确删除表情符号?

2 个答案:

答案 0 :(得分:4)

正则表达式已过时。它似乎涵盖了Emoji定义的Unicode 8.0之前的版本(因为在Unicode 9.0中添加了U+1F91D HANDSHAKE)。另一种方法只是强制编码为ASCII的效率很低的方法,而只是删除Emoji时,这几乎是您所不想要的(并且可以使用text.encode('ascii', 'ignore').decode('ascii')更轻松,更有效地实现)。

如果您需要最新的正则表达式,请从a package that is actively trying to keep up-to-date on Emoji中获取一个;它特别支持生成这样的正则表达式:

import emoji

def remove_emoji(text):
    return emoji.get_emoji_regexp().sub(u'', text)

该软件包当前是Unicode 11.0的最新版本,并具有可以快速更新到将来发行版的基础结构。您的项目所要做的就是在有新版本发布时进行升级。

使用示例输入进行演示:

>>> print(remove_emoji(u'తెలంగాణ రియల్ ఎస్టేట్ '))
తెలంగాణ రియల్ ఎస్టేట్ 
>>> print(remove_emoji(u'Testరియల్ ఎస్టేట్ A.P&T.S. '))
Testరియల్ ఎస్టేట్ A.P&T.S. 

请注意,正则表达式适用于 Unicode文本,对于Python 2,请确保已从str解码为unicode;对于Python 3,请确保已从bytes解码到str 第一

表情符号这些天是复杂的野兽。以上内容将删除完整有效的表情符号。如果您的Emoji组件不完整,例如skin-tone codepoints(仅与 specific Emoji结合使用),则在删除它们方面会遇到更多麻烦。肤色代码点很容易(以后只需删除这5个代码点即可),但是有一个whole host of combinations由无辜的字符组成,例如♀U + 2640 FEMALE SIGN或♂U + 2642 MALE SIGN以及{ {3}}和variant selectors其他上下文中也具有特定含义,并且您不能仅将它们正则表达式化,除非您不介意使用Devanagari破坏文本,或者卡纳达语或中日韩象形文字,仅举几个例子。

也就是说,以下Unicode 11.0代码点可能安全删除(基于过滤U+200D ZERO-WIDTH JOINER):

20E3          ;  (⃣)     combining enclosing keycap
FE0F          ; ()        VARIATION SELECTOR-16
1F1E6..1F1FF  ; (..)  regional indicator symbol letter a..regional indicator symbol letter z
1F3FB..1F3FF  ; (..)  light skin tone..dark skin tone
1F9B0..1F9B3  ; (..) red-haired..white-haired
E0020..E007F  ; (..)      tag space..cancel tag

可以通过创建新的正则表达式来匹配它们来删除它们:

import re
try:
    uchr = unichr  # Python 2
    import sys
    if sys.maxunicode == 0xffff:
        # narrow build, define alternative unichr encoding to surrogate pairs
        # as unichr(sys.maxunicode + 1) fails.
        def uchr(codepoint):
            return (
                unichr(codepoint) if codepoint <= sys.maxunicode else
                unichr(codepoint - 0x010000 >> 10 | 0xD800) +
                unichr(codepoint & 0x3FF | 0xDC00)
            )
except NameError:
    uchr = chr  # Python 3

# Unicode 11.0 Emoji Component map (deemed safe to remove)
_removable_emoji_components = (
    (0x20E3, 0xFE0F),             # combining enclosing keycap, VARIATION SELECTOR-16
    range(0x1F1E6, 0x1F1FF + 1),  # regional indicator symbol letter a..regional indicator symbol letter z
    range(0x1F3FB, 0x1F3FF + 1),  # light skin tone..dark skin tone
    range(0x1F9B0, 0x1F9B3 + 1),  # red-haired..white-haired
    range(0xE0020, 0xE007F + 1),  # tag space..cancel tag
)
emoji_components = re.compile(u'({})'.format(u'|'.join([
    re.escape(uchr(c)) for r in _removable_emoji_components for c in r])),
    flags=re.UNICODE)

然后更新上面的remove_emoji()函数以使用它:

def remove_emoji(text, remove_components=False):
    cleaned = emoji.get_emoji_regexp().sub(u'', text)
    if remove_components:
        cleaned = emoji_components.sub(u'', cleaned)
    return cleaned

答案 1 :(得分:0)

如果您使用regex库而不是re库,则可以访问Unicode属性,然后可以将函数更改为

def remove_emoji(self, string):
    emoji_pattern = re.compile("[\P{L}&&\P{D}&&\P{Z}&&\P{M}]", flags=re.UNICODE)
    return emoji_pattern.sub(r'', string)

将保留所有字母,数字,分隔符和标记(重音符号)