如何确定Python字符串是否包含表情符号?

时间:2016-09-02 23:18:46

标签: python emoji

我之前看到过这个问题的回答,但是没有一个是最近的,没有一个在Python 3中为我工作。我有一个字符串列表,我只是想确定哪些包含表情符号。最快的方法是什么?

更具体地说,我有一个冗长的AB测试电子邮件主题行列表,我正在尝试确定哪些主题行包含表情符号。

1 个答案:

答案 0 :(得分:1)

this linkthis link都将©和其他常见字符统计为表情符号。前者也有轻微的错误,而后者似乎仍然不起作用。

这是一个使用this newer datathis documentation在保守方面犯错误的实现。它只考虑使用unicode属性Emoji_Presentation标记的代码点(这意味着它绝对是表情符号),或仅使用属性Emoji标记的代码点(这意味着它默认为文本但它可能是一个表情符号),后面是一个特殊的变体选择器代码点fe0f,它默认为表情符号。我说这是保守的原因是因为某些系统对于fe0f并不那么挑剔,并且会将字符视为表情符号(请阅读有关此here的更多信息)。

import re
from collections import defaultdict


def parse_line(line):
    """Return a pair (property, codepoints) where property is a string and
       codepoints is a set of int unicode code points"""
    pat = r'([0-9A-Z]+)(\.\.[0-9A-Z]+)? + ; +(\w+) + #.*'
    match = re.match(pat, line)
    assert match

    codepoints = set()

    start = int(match.group(1), 16)

    if match.group(2):
        trimmed = match.group(2)[2:]
        end = int(trimmed, 16) + 1
    else:
        end = start + 1

    for cp in range(start, end):
        codepoints.add(cp)

    return (match.group(3), codepoints)


def parse_emoji_data():
    """Return a dictionary mapping properties to code points"""
    result = defaultdict(set)
    with open('emoji-data.txt', mode='r', encoding='utf-8') as f:
        for line in f:
            if '#' != line[0] and len(line.strip()) > 0:
                property, cp = parse_line(line)
                result[property] |= cp
    return result


def test_parse_emoji_data():
    sets = parse_emoji_data()
    sizes = {
        'Emoji': 1123,
        'Emoji_Presentation': 910,
        'Emoji_Modifier': 5,
        'Emoji_Modifier_Base': 83,
    }
    for k, v in sizes.items():
        assert len(sets[k]) == v


def contains_emoji(text):
    """
    Return true if the string contains either a code point with the
    `Emoji_Presentation` property, or a code point with the `Emoji`
    property that is followed by \uFE0F
    """
    sets = parse_emoji_data()
    for i, ch in enumerate(text):
        if ord(ch) in sets['Emoji_Presentation']:
            return True
        elif ord(ch) in sets['Emoji']:
            if len(text) > i+1 and text[i+1] == '\ufe0f':
                return True
    return False

test_parse_emoji_data()
assert not contains_emoji('hello')
assert not contains_emoji('hello :) :D 125% #%&*(@#%&!@(^*(')
assert contains_emoji('here is a smiley \U0001F601 !!!')

要运行此功能,您需要在工作目录中使用ftp://ftp.unicode.org/Public/emoji/3.0/emoji-data.txt

一旦正则表达式模块支持表情符号属性,它就会更容易使用它。