如何使用python在字符串中查找和计算表情符号?

ble*_*man 9 python regex string unicode

已在link1,link2,link3处针对基于文本的表情符号解决了此主题.但是,我想做一些与匹配简单表情符号略有不同的东西.我正在整理包含表情符号图标的推文.以下unicode信息仅包含此类表情符号:pdf.

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

我向前走的方向似乎不是最佳选择,我正在寻求一些帮助.正如您在下面的脚本中看到的那样,我只是计划从命令行完成工作:

$cat <file containing the strings with emoticons> | ./emo.py
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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

"笑脸图释岩!在此输入图像描述 我喜欢你在此输入图像描述".

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

aba*_*ert 17

首先,根本不需要在这里进行编码.你有一个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))
Run Code Online (Sandbox Code Playgroud)

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

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

计算单词,你可以单独做:

wordcount = len(s.split())
Run Code Online (Sandbox Code Playgroud)

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

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

正如@strangefeatures指出的那样,3.3之前的Python版本允许"窄Unicode"构建.而且,例如,大多数CPython Windows构建都很窄.在窄版本,字符只能在范围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)
Run Code Online (Sandbox Code Playgroud)

如果你不担心接受假UTF-16,你可以在最后一种情况下放弃第二个条件.

如果将其转换为regexp并不明显,这里是[\U0001e050-\U0001fbbf]UTF-16-BE 范围的示例:

(\ud838[\udc50-\udfff])|([\ud839-\ud83d].)|(\ud83e[\udc00-\udfbf])
Run Code Online (Sandbox Code Playgroud)

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

\ud83d[\ude00-\ude50]
Run Code Online (Sandbox Code Playgroud)

最后一招,如果你实际上不知道你是否会得到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)
Run Code Online (Sandbox Code Playgroud)


she*_*nzy 5

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

\n\n
import emoji\nimport regex\n\ndef split_count(text):\n    emoji_counter = 0\n    data = regex.findall(r\'\\X\', text)\n    for word in data:\n        if any(char in emoji.UNICODE_EMOJI for char in word):\n            emoji_counter += 1\n            # Remove from the given text the emojis\n            text = text.replace(word, \'\') \n\n    words_counter = len(text.split())\n\n    return emoji_counter, words_counter\n
Run Code Online (Sandbox Code Playgroud)\n\n

测试:

\n\n
line = "hello \xe2\x80\x8d emoji hello \xe2\x80\x8d\xe2\x80\x8d\xe2\x80\x8d how are  you today"\ncounter = split_count(line)\nprint("Number of emojis - {}, number of words - {}".format(counter[0], counter[1]))\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出:

\n\n
Number of emojis - 5, number of words - 7\n
Run Code Online (Sandbox Code Playgroud)\n