python表情符号编码大全_Emoji的编码以及常见问题处理
我在虎嗅上看過(guò)一篇關(guān)于Emoji的趣聞, 特別有意思, 在這里跟大家分享一下。里面提到了Emoji是怎么誕生的。
1999年前后,日本一個(gè)名叫栗田穰崇的年輕人,和許多直男一樣, 給女友發(fā)的短信經(jīng)常會(huì)被誤解。比如,“知道了”被解讀成“生氣了”、“不耐煩了”,隨后引發(fā)冷戰(zhàn)。 于是少年栗田想:“如果能在文字里插入一些表情符號(hào)來(lái)表達(dá)感情,大家應(yīng)該會(huì)需要吧!”
原始的Emoji就這么誕生了。
Emoji極大地豐富了我們的生活和通訊交流。Emoji誕生自程序員,但反過(guò)來(lái)對(duì)程序員也造成過(guò)一些困擾。
尤其對(duì)于面向C端的產(chǎn)品開(kāi)發(fā)者, 用戶越來(lái)越習(xí)慣于輸入Emoji, 因此處理字符時(shí)遇到Emoji也只會(huì)越來(lái)越頻繁。
Emoji的編碼
Emoji字符是Unicode字符集中一部分. 特定形象的Emoji表情符號(hào)對(duì)應(yīng)到特定的Unicode字節(jié)。
常見(jiàn)的Emoji表情符號(hào)在Unicode字符集中的范圍和具體的字節(jié)映射關(guān)系, 可通過(guò)Emoji Unicode Tables查看到。
有意思的是, 在Emoji Unicode Tables表中,還給出了同一個(gè)Emoji表情在不同系統(tǒng)中的字體(是字體沒(méi)錯(cuò), Emoji的樣式可通過(guò)字體文件改變)。
關(guān)于Emoji的最權(quán)威資料, 可以在Unicode? Emoji Charts上查閱到。
截止我寫這篇文章的時(shí)刻, Emoji Charts 的最新版本是v3.0, v4.0還只是處于Beta階段。
題外話補(bǔ)充一點(diǎn): Unicode是一種字符編碼方法,它是由國(guó)際組織設(shè)計(jì),可以容納全世界所有語(yǔ)言文字的編碼方案。
我們所知道的UTF-8、UTF-16等編碼, 是對(duì)Unicode的不同實(shí)現(xiàn)方式。
如果要深入了解更多關(guān)于ASCII、Unicode、UTF-8、gb2312、gbk等編碼的相關(guān)知識(shí),在這里強(qiáng)烈推薦幾篇文章,講得非常好。
一些特殊的Emoji
在眾多Emoji中, 有一些特殊的Emoji 并沒(méi)有顯示的樣式, 只是起到了控制的作用。這些控制型的Emoji 與基礎(chǔ)Emoji 出現(xiàn)在一起, 可以展示更多的樣式。
比如 "變量選擇器-15"(VARIATION SELECTOR-15, 簡(jiǎn)寫VS-15): , 作用是讓基礎(chǔ)Emoji 變成更接近文本樣式(text-style);
而 "變量選擇器-16"(VARIATION SELECTOR-16, 簡(jiǎn)寫VS-16): , 作用則是讓基礎(chǔ)Emoji 變成更接近Emoji樣式(emoji-style).
VS-15 和 VS-16 加在基礎(chǔ)Emoji字符的后面, 可以起到控制作用(前提是必須系統(tǒng)支持, 否則會(huì)被忽略)。
用一段Python代碼來(lái)演示該例子:
# -*- coding: utf-8 -*-
# more info to see https://en.wikipedia.org/wiki/Emoji
# 符號(hào)分別是上圖(截圖自wiki)中的符號(hào), 最后再加上一個(gè)“狗”的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 '-' * 20
# 后面加上VS-15
for code in sample_list:
print (code + u'\uFE0E'),
print '-' * 20
# 后面加上VS-16
for code in sample_list:
print (code + u'\uFE0F'),
其輸出如下圖, 第一行是原樣式,第二行是加上VS-15后的樣式,第三行是加上VS-16后的樣式:
另外, 還有一些控制型的Emoji, 可以對(duì)人體膚色進(jìn)行改變,改變對(duì)象僅限于"表示人身體部位的Emoji".
它們分別是: – 共五個(gè), 分別簡(jiǎn)稱為: FITZ-1-2, FITZ-3, FITZ-4, FITZ-5, FITZ-6.
還有一個(gè)特殊的控制符: (ZERO WIDTH JOINER, 簡(jiǎn)寫ZWJ), 起到了連接Emoji的作用, 從而將多個(gè)Emoji變成一個(gè)Emoji來(lái)顯示. 同樣,前提是必須系統(tǒng)支持, 否則會(huì)被忽略.
使用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 分別是: 空字符串,表示默認(rèn) 白種人 -->(不斷加深膚色) 黑種人
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 '-' * 20
# Emoji的連接符 (英文名為: ZERO WIDTH JOINER, 簡(jiǎn)寫ZWJ )
# 如果系統(tǒng)支持: 連接(男人 + ZWJ + 女人 + ZWJ + 女孩)
print u'\U0001F468' + u'\u200D' + u'\U0001F469' + u'\u200D' + u'\U0001F467'
# 如果系統(tǒng)不支持: 連接(狗 + ZWJ + 貓 + ZWJ + 老鼠)
print u'\U0001f436' + u'\u200D' + u'\U0001f431' + u'\u200D' + u'\U0001f42d'
其輸出如下圖:
以上內(nèi)容參考自維基百科
對(duì)Emoji 的介紹到該小節(jié)結(jié)束, 下面內(nèi)容是一些關(guān)于實(shí)際中可能遇到的技術(shù)問(wèn)題的解決方法。
MySQL存儲(chǔ)Emoji
使用MySQL存儲(chǔ)Emoji, 只需要數(shù)據(jù)表的字符集為utf8mb4即可, 即CHARSET=utf8mb4.
如果想要知道你的MySQL數(shù)據(jù)庫(kù)是否支持utf8mb4編碼, 可通過(guò)show charset; 輸出當(dāng)前安裝的MySQL所支持的所有字符集, 查看輸出中是否包含有utf8mb4.
另外, 有一些比較老的業(yè)務(wù), 可能一開(kāi)始設(shè)計(jì)時(shí)沒(méi)考慮到需要支持Emoji, 那就需要修改數(shù)據(jù)庫(kù)或數(shù)據(jù)表的字符集.
查看MySQL說(shuō)支持的所有字符集
mysql> show charset;
查看某張表當(dāng)前的字符集
mysql> show create table ;
創(chuàng)建默認(rèn)字符集為utf8mb4的數(shù)據(jù)庫(kù).在該數(shù)據(jù)庫(kù)中,如果創(chuàng)建表時(shí)是不指明字符集,則默認(rèn)utf8mb4.
mysql> create database default charset utf8mb4;
創(chuàng)建字符集為utf8mb4的表, 數(shù)據(jù)庫(kù)的默認(rèn)字符集非utf8mb4也沒(méi)問(wèn)題.
mysql> create table `` (Column定義, Column定義, ...) DEFAULT CHARSET=utf8mb4;
修改已存在的數(shù)據(jù)庫(kù)的字符集
mysql> alter database default charset = utf8mb4;
修改已存在的表的字符集
mysql> alter table default charset = utf8mb4;
使用正則表達(dá)式匹配Emoji
很可惜, Emoji的范圍并沒(méi)有明確的定義。正如上面提到了,Emoji Charts目前最新版本是v3.0, 未來(lái)Emoji的范圍還會(huì)不斷擴(kuò)大。而且Emoji 在Unicode的分配中并不是連續(xù)的區(qū)間。
所以, 在這里我只能給出一個(gè)可行的匹配區(qū)間, 盡可能涵蓋了基本常見(jiàn)的Emoj。
該匹配區(qū)間中會(huì)包含一些未定義的字符, 可能在某些系統(tǒng)會(huì)有定義,但是在另外的系統(tǒng)中并沒(méi)有定義。畢竟Emoji是商業(yè)的產(chǎn)物。
- # symbols & pictographs
- # emoticons
- # transport & map symbols
- # other
下面使用Python代碼來(lái)演示如何使用正則表達(dá)式替換(或找出)字符串中的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...來(lái)處理代碼, 是考慮到 UCS-2 (Narrow UCS-2 build) 和 UCS-4 (Wide UCS-4 build) 的區(qū)別.
該Demo例子參考了stackoverflow上的精彩回答, 解答了我對(duì)此的困惑。
關(guān)于UCS-2和UCS-4的區(qū)別, 在上面提到的擴(kuò)展閱讀程序員趣味讀物:談?wù)刄nicode編碼中有提到, 值得一看.
本文中使用到的示例代碼,可以在我的github下載到。
帶有Emoji的字符串截取
在Python、JavaScript 這類編程語(yǔ)言中, 一個(gè)中文字符的長(zhǎng)度為1,但是對(duì)大部分的Emoji(并非全部), 取長(zhǎng)度則是2。下面使用Python做演示。
以中文的"漢"字取長(zhǎng)度為例,取長(zhǎng)度為1:
>>>len(u'漢')
1
而對(duì)于Emoji,以(該Emoji是一只萌萌的狗)為例,取長(zhǎng)度為2:
>>>len(u'\U0001f436')
2
那么, 這就存在一個(gè)隱患, 在對(duì)字符串進(jìn)行截?cái)鄷r(shí)可能從中間截?cái)? 導(dǎo)致該字符顯示為亂碼, 甚至引發(fā)報(bào)錯(cuò)。
下面例子中, 對(duì)字符串進(jìn)行截取時(shí),正好從的中間截?cái)嗔?#xff0c;出現(xiàn)了亂碼:
>>>u'這是一只可愛(ài)的狗狗\U0001f436'.__len__()
11
>>>u'這是一只可愛(ài)的狗狗\U0001f436'[0:10]
這是一只可愛(ài)的狗狗???
實(shí)際場(chǎng)景中,對(duì)字符串進(jìn)行截?cái)嗍欠浅3R?jiàn)的需求,而且字符串往往可能是用戶高度自由的輸入內(nèi)容, 那么包含Emoji的可能性其實(shí)是很高的。
一個(gè)具體的場(chǎng)景就是: 你正在開(kāi)發(fā)了一款社交APP, 允許用戶保存文字記錄, 然后在應(yīng)用的某個(gè)地方, 又需要顯示這些文字記錄的摘要,摘要只顯示用戶輸入的前100個(gè)字符, 超出部分用省略號(hào)表示。
這種情況下,就不可避免的可能發(fā)生Emoji在中間被截?cái)嗟膯?wèn)題。
解決方案也有多種:
全文進(jìn)行正則匹配, 去掉大部分Emoji, 但是文本長(zhǎng)度過(guò)長(zhǎng)的情況消耗太大, 不值得.
先截取前200個(gè)字符, 匹配去掉Emoji再截取100個(gè)字符. 貌似可行. 但如果極端條件下前200個(gè)字符都是Emoji怎么辦? 管他的.
運(yùn)用上面提到的擴(kuò)展閱讀: 字符編碼筆記:ASCII,Unicode和UTF-8中提到的UTF-8的編碼規(guī)則, 對(duì)截?cái)嗪笞址淖詈笞址M(jìn)行檢查, 發(fā)現(xiàn)是截?cái)嗟淖址催M(jìn)行剔除。該方案可行, 不過(guò)你需要自己去實(shí)現(xiàn)了。
允許一定概率出現(xiàn)亂碼, 亂碼就亂碼吧,概率不高,不影響主要體驗(yàn)。將更多精力放在避免其他bug上吧。
總結(jié)
以上是生活随笔為你收集整理的python表情符号编码大全_Emoji的编码以及常见问题处理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python两个时间内的工作日_如何在P
- 下一篇: python返回长度值_Python 文