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

标签 python regex string unicode

此主题已在 link1 上针对基于文本的表情符号进行了处理, link2 , link3 .但是,我想做一些与匹配简单表情略有不同的事情。我正在整理包含表情符号图标的推文。以下 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

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

“笑脸表情棒棒哒!enter image description here我喜欢你enter image description here。”

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

最佳答案

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

A character class可以包含一系列字符,方法是用连字符指定第一个和最后一个。并且您可以使用 \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 构建都很窄。在窄版中,字符只能在 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,则可以在最后一种情况下省略第二个条件。

如果它如何转换为正则表达式不是很明显,这里有一个 UTF-16-BE 格式的范围 [\U0001e050-\U0001fbbf] 的例子:

(\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)

关于python - 如何使用 python 在字符串中查找和计算表情符号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19149186/

相关文章:

C# - 路径中的非法字符

C - cs50.h GetString 错误

c++ - 存储 strtok() token 的值?

python - 在Python中创建列表的空列表

python - 如何让 python Zookeeper api 工作?

python - python中的Or语句问题

php - 用 PHP 编写一个简单的 preg_replace

python - 代码在函数外部工作,但在函数内部不起作用(python)

regex - 如何使用Regex(Google Analytics(分析))排除特定的URL路径?

c# - 在正则表达式匹配中保留换行符,c#