12

此主题已针对link1link2link3上的基于文本的表情符号进行了处理。但是,我想做一些与匹配简单表情符号略有不同的事情。我正在整理包含表情符号图标的推文。以下 unicode 信息仅包含此类表情符号:pdf

使用带有英文单词的字符串,该字符串还包含pdf中的任何这些表情符号,我希望能够将表情符号的数量与单词的数量进行比较。

我往下走的方向似乎不是最好的选择,我正在寻求帮助。正如您在下面的脚本中看到的那样,我只是打算从命令行完成这项工作:

$cat <file containing the strings with emoticons> | ./emo.py

emo.py 伪脚本:

import re
import sys

for row in sys.stdin:
    print row.decode('utf-8').encode("ascii","replace")
    #insert regex to find the emoticons
    if match:
       #do some counting using .split(" ")
       #print the counting

我遇到的问题是解码/编码。我还没有找到如何编码/解码字符串的好选择,所以我可以正确找到图标。我要搜索以查找单词和表情符号数量的字符串示例如下:

“笑脸表情摇滚!在此处输入图像描述我喜欢你在此处输入图像描述。”

挑战:你能制作一个脚本来计算这个字符串中的单词和表情符号的数量吗?请注意,表情符号都位于单词旁边,中间没有空格。

4

4 回答 4

19

首先,这里根本不需要编码。你有一个 Unicode 字符串,re引擎可以处理 Unicode,所以就使用它。

字符类可以包含一系列字符,方法是指定第一个字符和最后一个字符,并在它们之间加上连字符。并且您可以指定您不知道如何使用\U转义序列键入的 Unicode 字符。所以:

import re

s=u"Smiley emoticon rocks!\U0001f600 I like you.\U0001f601"
count = len(re.findall(ru'[\U0001f600-\U0001f650]', s))

或者,如果字符串足够大以至于构建整个findall列表似乎很浪费:

emoticons = re.finditer(ru'[\U0001f600-\U0001f650]', s)
count = sum(1 for _ in emoticons)

数单词,你可以分开做:

wordcount = len(s.split())

如果您想一次完成所有操作,可以使用交替组:

word_and_emoticon_count = len(re.findall(ru'\w+|[\U0001f600-\U0001f650]', s))

正如@strangefeatures 指出的那样,3.3 之前的 Python 版本允许“窄 Unicode”构建。而且,例如,大多数 CPython Windows 版本都很窄。在狭窄的构建中,字符只能在 to 范围U+0000U+FFFF。没有办法搜索这些字符,但没关系,因为它们不存在可搜索;如果您在编译正则表达式时遇到“无效范围”错误,您可以假设它们不存在。

当然,除了很有可能无论您从何处获取实际字符串,它们都是 UTF-16-BE 或 UTF-16-LE,因此字符确实存在,它们只是被编码为代理对. 你想匹配那些代理对,对吧?因此,您需要将您的搜索转换为代理对搜索。也就是说,将您的高代码点和低代码点转换为代理对代码单元,然后(用 Python 术语)搜索:

(lead == low_lead and lead != high_lead and low_trail <= trail <= DFFF or
 lead == high_lead and lead != low_lead and DC00 <= trail <= high_trail or
 low_lead < lead < high_lead and DC00 <= trail <= DFFF)

如果您不担心接受伪造的 UTF-16,则可以在最后一种情况下省略第二个条件。

如果不清楚如何将其转换为正则表达式,这里有一个[\U0001e050-\U0001fbbf]UTF-16-BE 范围的示例:

(\ud838[\udc50-\udfff])|([\ud839-\ud83d].)|(\ud83e[\udc00-\udfbf])

当然,如果您的范围足够小,low_lead == high_lead这会变得更简单。例如,可以使用以下命令搜索原始问题的范围:

\ud83d[\ude00-\ude50]

最后一个技巧,如果您实际上不知道您将获得 UTF-16-LE 还是 UTF-16-BE(并且 BOM 与您正在搜索的数据相距甚远):因为没有代理线索或跟踪代码单元作为独立字符或一对的另一端有效,您可以双向搜索:

(\ud838[\udc50-\udfff])|([\ud839-\ud83d][\udc00-\udfff])|(\ud83e[\udc00-\udfbf])|
([\udc50-\udfff]\ud838)|([\udc00-\udfff][\ud839-\ud83d])|([\udc00-\udfbf]\ud83e)
于 2013-10-03T01:52:32.247 回答
4

我的解决方案包括emojiregex模块。regex 模块支持识别字素簇(Unicode 代码点序列呈现为单个字符),因此我们可以计算一次像 ‍‍‍ 这样的表情符号,尽管它由 4 个表情符号组成。

import emoji
import regex

def split_count(text):
    emoji_counter = 0
    data = regex.findall(r'\X', text)
    for word in data:
        if any(char in emoji.UNICODE_EMOJI for char in word):
            emoji_counter += 1
            # Remove from the given text the emojis
            text = text.replace(word, '') 

    words_counter = len(text.split())

    return emoji_counter, words_counter

测试:

line = "hello ‍ emoji hello ‍‍‍ how are  you today"
counter = split_count(line)
print("Number of emojis - {}, number of words - {}".format(counter[0], counter[1]))

输出:

Number of emojis - 5, number of words - 7
于 2018-03-12T18:51:39.547 回答
0

如果您尝试读取 ascii 范围之外的 unicode 字符,请不要转换ascii 范围。只需将其保留为 unicode 并从那里开始工作(未经测试):

import sys

count = 0
emoticons = set(range(int('1f600',16), int('1f650', 16)))
for row in sys.stdin:
    for char in row:
        if ord(char) in emoticons:
            count += 1
print "%d emoticons found" % count

不是最好的解决方案,但它应该工作。

于 2013-10-03T01:16:13.487 回答
0

这是我使用的解决方案re

import re
text = "your text with emojis"
em_count = len(re.findall(r'[^\w\s,.]', text))
print(em_count)
于 2022-02-08T04:04:06.737 回答