python表情符号编码大全_Emoji的编码以及常见问题处理

我在虎嗅上看过一篇关于Emoji的趣闻, 特别有意思, 在这里跟大家分享一下。里面提到了Emoji是怎么诞生的。

1999年前后,日本一个名叫栗田穰崇的年轻人,和许多直男一样, 给女友发的短信经常会被误解。比如,“知道了”被解读成“生气了”、“不耐烦了”,随后引发冷战。 于是少年栗田想:“如果能在文字里插入一些表情符号来表达感情,大家应该会需要吧!”

原始的Emoji就这么诞生了。

Emoji极大地丰富了我们的生活和通讯交流。Emoji诞生自程序员,但反过来对程序员也造成过一些困扰。

尤其对于面向C端的产品开发者, 用户越来越习惯于输入Emoji, 因此处理字符时遇到Emoji也只会越来越频繁。

Emoji的编码

Emoji字符是Unicode字符集中一部分. 特定形象的Emoji表情符号对应到特定的Unicode字节。

常见的Emoji表情符号在Unicode字符集中的范围和具体的字节映射关系, 可通过Emoji Unicode Tables查看到。

有意思的是, 在Emoji Unicode Tables表中,还给出了同一个Emoji表情在不同系统中的字体(是字体没错, Emoji的样式可通过字体文件改变)。

关于Emoji的最权威资料, 可以在Unicode® Emoji Charts上查阅到。

截止我写这篇文章的时刻, Emoji Charts 的最新版本是v3.0, v4.0还只是处于Beta阶段。

题外话补充一点: Unicode是一种字符编码方法,它是由国际组织设计,可以容纳全世界所有语言文字的编码方案。

我们所知道的UTF-8、UTF-16等编码, 是对Unicode的不同实现方式。

如果要深入了解更多关于ASCII、Unicode、UTF-8、gb2312、gbk等编码的相关知识,在这里强烈推荐几篇文章,讲得非常好。

一些特殊的Emoji

在众多Emoji中, 有一些特殊的Emoji 并没有显示的样式, 只是起到了控制的作用。这些控制型的Emoji 与基础Emoji 出现在一起, 可以展示更多的样式。

比如 "变量选择器-15"(VARIATION SELECTOR-15, 简写VS-15): , 作用是让基础Emoji 变成更接近文本样式(text-style);

而 "变量选择器-16"(VARIATION SELECTOR-16, 简写VS-16): , 作用则是让基础Emoji 变成更接近Emoji样式(emoji-style).

VS-15 和 VS-16 加在基础Emoji字符的后面, 可以起到控制作用(前提是必须系统支持, 否则会被忽略)。

用一段Python代码来演示该例子:

# -*- coding: utf-8 -*-

# more info to see https://en.wikipedia.org/wiki/Emoji

# 符号分别是上图(截图自wiki)中的符号, 最后再加上一个“狗”的Emoji

sample_list = [u'\u2139', u'\u231B', u'\u26A0', u'\u2712', u'\u2764', u'\U0001F004', u'\U0001F21A', u'\U0001f436', ]

# 输出原样式

for code in sample_list:

print code,

print

print '-' * 20

# 后面加上VS-15

for code in sample_list:

print (code + u'\uFE0E'),

print

print '-' * 20

# 后面加上VS-16

for code in sample_list:

print (code + u'\uFE0F'),

其输出如下图, 第一行是原样式,第二行是加上VS-15后的样式,第三行是加上VS-16后的样式:

另外, 还有一些控制型的Emoji, 可以对人体肤色进行改变,改变对象仅限于"表示人身体部位的Emoji".

它们分别是: 共五个, 分别简称为: FITZ-1-2, FITZ-3, FITZ-4, FITZ-5, FITZ-6.

还有一个特殊的控制符: (ZERO WIDTH JOINER, 简写ZWJ), 起到了连接Emoji的作用, 从而将多个Emoji变成一个Emoji来显示. 同样,前提是必须系统支持, 否则会被忽略.

使用Python代码演示 FITZ-* 和 ZWJ:

# -*- coding: utf-8 -*-

# more info to see https://en.wikipedia.org/wiki/Emoji

# man_list 分别是: 男孩 女孩 男人 女人

man_list = [u'\U0001F466', u'\U0001F467', u'\U0001F468', u'\U0001F469']

# skin_color_list 分别是: 空字符串,表示默认 白种人 -->(不断加深肤色) 黑种人

skin_color_list = ['', u'\U0001F3FB', u'\U0001F3FC', u'\U0001F3FD', u'\U0001F3FE', u'\U0001F3FF', ]

for man in man_list:

for color in skin_color_list:

print (man + color),

print

print '-' * 20

# Emoji的连接符 (英文名为: ZERO WIDTH JOINER, 简写ZWJ )

# 如果系统支持: 连接(男人 + ZWJ + 女人 + ZWJ + 女孩)

print u'\U0001F468' + u'\u200D' + u'\U0001F469' + u'\u200D' + u'\U0001F467'

# 如果系统不支持: 连接(狗 + ZWJ + 猫 + ZWJ + 老鼠)

print u'\U0001f436' + u'\u200D' + u'\U0001f431' + u'\u200D' + u'\U0001f42d'

其输出如下图:

以上内容参考自维基百科

对Emoji 的介绍到该小节结束, 下面内容是一些关于实际中可能遇到的技术问题的解决方法。

MySQL存储Emoji

使用MySQL存储Emoji, 只需要数据表的字符集为utf8mb4即可, 即CHARSET=utf8mb4.

如果想要知道你的MySQL数据库是否支持utf8mb4编码, 可通过show charset; 输出当前安装的MySQL所支持的所有字符集, 查看输出中是否包含有utf8mb4.

另外, 有一些比较老的业务, 可能一开始设计时没考虑到需要支持Emoji, 那就需要修改数据库或数据表的字符集.

查看MySQL说支持的所有字符集

mysql> show charset;

查看某张表当前的字符集

mysql> show create table ;

创建默认字符集为utf8mb4的数据库.在该数据库中,如果创建表时是不指明字符集,则默认utf8mb4.

mysql> create database default charset utf8mb4;

创建字符集为utf8mb4的表, 数据库的默认字符集非utf8mb4也没问题.

mysql> create table `` (Column定义, Column定义, ...) DEFAULT CHARSET=utf8mb4;

修改已存在的数据库的字符集

mysql> alter database default charset = utf8mb4;

修改已存在的表的字符集

mysql> alter table default charset = utf8mb4;

使用正则表达式匹配Emoji

很可惜, Emoji的范围并没有明确的定义。正如上面提到了,Emoji Charts目前最新版本是v3.0, 未来Emoji的范围还会不断扩大。而且Emoji 在Unicode的分配中并不是连续的区间。

所以, 在这里我只能给出一个可行的匹配区间, 尽可能涵盖了基本常见的Emoj。

该匹配区间中会包含一些未定义的字符, 可能在某些系统会有定义,但是在另外的系统中并没有定义。毕竟Emoji是商业的产物。

- # symbols & pictographs

- # emoticons

- # transport & map symbols

- # other

下面使用Python代码来演示如何使用正则表达式替换(或找出)字符串中的Emoji:

# -*- coding: utf-8 -*-

import re

try:

# Wide UCS-4 build

myre = re.compile(u'['

u'\U0001F300-\U0001F64F'

u'\U0001F680-\U0001F6FF'

u'\u2600-\u2B55]+',

re.UNICODE)

except re.error:

# Narrow UCS-2 build

myre = re.compile(u'('

u'\ud83c[\udf00-\udfff]|'

u'\ud83d[\udc00-\ude4f\ude80-\udeff]|'

u'[\u2600-\u2B55])+',

re.UNICODE)

sss = u'I have a dog \U0001f436 . You have a cat \U0001f431 ! I smile \U0001f601 to you!'

print myre.sub('[Emoji]', sss) # 替换字符串中的Emoji

print myre.findall(sss) # 找出字符串中的Emoji

输出如下:

I have a dog [Emoji] . You have a cat [Emoji] ! I smile [Emoji] to you!

[u'\U0001f436', u'\U0001f431', u'\U0001f601']

上面例子中, 之所以使用try...except...来处理代码, 是考虑到 UCS-2 (Narrow UCS-2 build) 和 UCS-4 (Wide UCS-4 build) 的区别.

该Demo例子参考了stackoverflow上的精彩回答, 解答了我对此的困惑。

关于UCS-2和UCS-4的区别, 在上面提到的扩展阅读程序员趣味读物:谈谈Unicode编码中有提到, 值得一看.

本文中使用到的示例代码,可以在我的github下载到。

带有Emoji的字符串截取

在Python、JavaScript 这类编程语言中, 一个中文字符的长度为1,但是对大部分的Emoji(并非全部), 取长度则是2。下面使用Python做演示。

以中文的"汉"字取长度为例,取长度为1:

>>>len(u'汉')

1

而对于Emoji,以(该Emoji是一只萌萌的狗)为例,取长度为2:

>>>len(u'\U0001f436')

2

那么, 这就存在一个隐患, 在对字符串进行截断时可能从中间截断, 导致该字符显示为乱码, 甚至引发报错。

下面例子中, 对字符串进行截取时,正好从的中间截断了,出现了乱码:

>>>u'这是一只可爱的狗狗\U0001f436'.__len__()

11

>>>u'这是一只可爱的狗狗\U0001f436'[0:10]

这是一只可爱的狗狗???

实际场景中,对字符串进行截断是非常常见的需求,而且字符串往往可能是用户高度自由的输入内容, 那么包含Emoji的可能性其实是很高的。

一个具体的场景就是: 你正在开发了一款社交APP, 允许用户保存文字记录, 然后在应用的某个地方, 又需要显示这些文字记录的摘要,摘要只显示用户输入的前100个字符, 超出部分用省略号表示。

这种情况下,就不可避免的可能发生Emoji在中间被截断的问题。

解决方案也有多种:

全文进行正则匹配, 去掉大部分Emoji, 但是文本长度过长的情况消耗太大, 不值得.

先截取前200个字符, 匹配去掉Emoji再截取100个字符. 貌似可行. 但如果极端条件下前200个字符都是Emoji怎么办? 管他的.

运用上面提到的扩展阅读: 字符编码笔记:ASCII,Unicode和UTF-8中提到的UTF-8的编码规则, 对截断后字符串的最后字符进行检查, 发现是截断的字符即进行剔除。该方案可行, 不过你需要自己去实现了。

允许一定概率出现乱码, 乱码就乱码吧,概率不高,不影响主要体验。将更多精力放在避免其他bug上吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/352016.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习套路三步走

机器学习的套路 1.model如何对现实的场景进行抽象2.model如何对参数进行求解3.model的效果如何评价1.抽象 例如线性回归,就是认为预测变量y和特征X之间存在线性关心,老掉牙的例子就是房价和地区收入,人口密度等等的线性关系 线性回归的数学假…

C及opencv指针释放问题

一个图像处理的项目运行时没有问题,最后关掉显示的图片时提醒触发一个断点,点击继续则出现以下画面:断点停留在释放指针的那一行。究其原因如下: 1.错用free释放IplImage* IplImage* input cvLoadImage("data/LOGO/2_1.jpg&…

gcc/g++基本命令简介

gcc & g现在是gnu中最主要和最流行的c & c编译器 。 g是c的命令,以.cpp为主,对于c语言后缀名一般为.c。这时候命令换做gcc即可。其实是无关紧要的。 其实编译器是根据gcc还是g来确定是按照C标准还是C标准编译链接。 下面以Test.cpp为例&#x…

python返回长度值_Python 文件 truncate() 方法(截断返回截取长度)

概述Python 文件 truncate() 方法用于截断文件并返回截断的字节长度。指定长度的话,就从文件的开头开始截断指定长度,其余内容删除;不指定长度的话,就从文件开头开始截断到当前位置,其余内容删除。语法truncate() 方法…

Opencv中IplImage的四字节对齐问题

一、结构解释IplImage数据结构体中有两个宽度:1 是width属性,表示图像的每行像素数;2 是widthStep属性,表示存储一行像素需要的字节数。在OpenCV里边,widthStep必须是4的倍数,从而实现字节对齐,…

庞佐错觉_水晶球错觉

庞佐错觉我注意到人们有时会避免进行彻底的测试。 对于某些人来说,这听起来像是伪造的,但请听我说…… 测试会产生被困的感觉,每引入一个新的测试,负担就会加重。 建立稳定,无干扰且质量保证的测试套件是一项艰巨的任务…

静态编译和动态编译区别

静态函数库 一般扩展名为(.a),这类的函数库通常扩展名为libxxx.a 。 这类函数库在编译的时候会直接整合到程序中,所以利用静态函数库编译成的文件会比较大,这类函数库最大的优点就是编译成功的可执行文件可以独立运行,…

python怎么爬取电影海报_python爬虫之通过BeautifulSoup获取豆瓣最新上映电影的海报...

0.目录1.分析页面2.初步代码3.完整代码4.总结5.补充1.分析页面上一次我们讲了xpath获取豆瓣最新上映电影的海报,这一次会分析如何使用BeautifulSoup获取。启程:python爬虫之通过xpath获取豆瓣最新上映电影的海报​zhuanlan.zhihu.com首先,进入…

switch使用中遇到的问题

switch分支语句中case判断不会进行隐式数据类型转换; 1 const fn (value) > {2 let str all;3 switch (value) {4 case :5 return all0;6 case 3:7 return all3;8 case 4:9 return all4;…

opencv读取视频并保存为图片

1.功能&#xff1a;opencv读取指定文件夹中的视频文件&#xff0c;按照一定的间隔截取某些帧&#xff0c;将这些帧图像连续命名&#xff0c;存储在指定文件夹里。 2.代码如下&#xff1a; &#xff08;1&#xff09;IplImage #include <stdlib.h> #include <stdio.h&g…

将Jython嵌入到您的Java代码库中

Jython是一个使用相当可靠的语法的快速Java脚本的好工具。 实际上&#xff0c;当使用jmx为您的Java应用程序实现一些维护或监视脚本时&#xff0c;它的运行效果非常好。 如果您与其他具有python背景的团队合作&#xff0c;则将python集成到您的java应用程序是绝对有意义的。 …

C语言的编译链接过程详解

学过C语言的人都应该知道&#xff0c;我们所编辑的C语言程序是不能直接放到机器上运行的&#xff0c;它只不过是一个带".c"后缀的文件&#xff08;也称为源代码&#xff09;而已&#xff0c;需要经过一定的处理才能转换成机器上可运行的可执行文件。我们将对C语言的这…

python 谷歌登录_用Python登录Gmail并发送Gmail邮件的教程

这篇快文介绍了使用Gmail作为您的e-mail服务器&#xff0c;通过Python的内置SMTP库发送电子邮件。它并不复杂&#xff0c;我保证。下面是如何在Python中登录GMail&#xff1a;import smtplib# The below code never changes, though obviously those variables need values.ses…

Linux wget命令详解

wget是一个下载文件的工具&#xff0c;它用在命令行下。对于Linux用户是必不可少的工具&#xff0c;我们经常要下载一些软件或从远程服务器恢复备份到本地服务器。 wget支持HTTP&#xff0c;HTTPS和FTP协议&#xff0c;可以使用HTTP代理。所谓的自动下载是指&#xff0c;wget可…

opencv连续读图

1.功能利用opencv连续读取指定文件夹中连续命名的图像&#xff0c;可以根据需要设置图像的命名间隔和图像的个数。 2.代码 #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> int main(int …

在要求输入数字处找到非数字字符_剑指 Offer 67. 把字符串转换成整数 leetcode 剑指offer系列...

点击专辑上方“蓝字”关注我吧题目难度: 中等原题链接[1]今天继续更新剑指 offer 系列, 老样子晚上 6 点 45 分准时更新公众号 每日精选算法题, 大家记得关注哦~ 另外在公众号里回复 offer 就能看到剑指 offer 系列当前连载的所有文章了题目描述写一个函数 StrToInt&#xff0c…

旅行商问题的n种解法

问题描述&#xff1a; 旅行商问题&#xff08;Traveling Salesman Problem,TSP&#xff09;是旅行商要到若干个城市旅行&#xff0c;各城市之间的费用是已知的&#xff0c;为了节省费用&#xff0c;旅行商决定从所在城市出发&#xff0c;到每个城市旅行一次后返回初始城市&…

将字符串中的指定字符全局替换

// 将 str 中的 a 替换为 Avar str abcabcabc;var result str.replace(a, A);console.log(result: result); // 输出 result:Abcabcabc // 将str 中所有的 a 替换为 Avar str abcabcabc;var result str.replace(/a/g, A);console.log(result: result); // 输出 result:…

Lintcode--5(37)--反转一个三位数

1、题目反转一个只有3位数的整数。123 反转之后是 321。900 反转之后是 9。 2、我的解答 class Solution { public:/*** param number: A 3-digit number.* return: Reversed number.*/int reverseInteger(int number) {int num[3] {0};int result;num[1] number/100;num[2] …

java未检查异常_Java中已检查和未检查的异常

java未检查异常Java有两种类型的异常-已检查和未检查。 简而言之&#xff0c;选中的是指开发人员可以从异常中合理恢复的情况&#xff0c;而未选中的异常是无法处理的编程错误。 本文介绍了何时使用哪种。 但这不是那么简单–受检查的异常使代码变得“丑陋”。 它们迫使开发人员…