人工智能-机器人聊天语库搭建

编码/解码问题是个大坑,其中的复杂性,大多来自历史包袱

由于计算机领域的分层架构和多平台问题,这个问题被进一步加剧,unicode的出现,给这个问题带来了曙光.

可是生活不总是那么美好的,有些时候,一不小心,我们还是会掉到满是泥沼的坑里

周末在凤凰书城看一本数据清洗相关的书,其中说道噪声数据的问题,有问题的编码是噪声的来源之一,书中分享了不少好用的方法,在便签里记了一些,加上之前笔记里的,正好整理成一篇文章

编码问题

这里引《中文编码杂谈》中关于乱码的讨论

在Linux平台上如果使用cat等命令查看文件中的中文内容时,可能出现乱码。这也是编码的问题。简单的说是文件时按照A编码保存,但是cat命令按照当前Locale设定的B编码去查看,在B和A不兼容的时候就出现了乱码。

核心概念

十分钟搞清字符集和字符编码

字符集

简单的说字符集就规定了某个文字对应的二进制数字存放方式(编码)和某串二进制数值代表了哪个文字(解码)的转换关系

字符编码

字符编码(英语:Character encoding)、字集码是把字符集中的字符编码为指定集合中某一对象(例如:比特模式、自然数序列、8位组或者电脉冲),以便文本在计算机中存储和通过通信网络的传递。常见的例子包括将拉丁字母表编码成摩斯电码和ASCII。其中,ASCII将字母、数字和其它符号编号,并用7比特的二进制来表示这个整数 --wikipedia

Unicode和UTF-8

Unicode对世界上大部分的文字系统进行了整理、编码,使得电脑可以用更为简单的方式来呈现和处理文字。

Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储

而UTF-8就是字符编码,是Unicode规则字库的一种实现形式

Python中的编码问题

Python编码和Unicode一文中描述了python中可能出现的一些编解码难题

原因之一是Python 2.x默认将所有的字符串当做ASCII来对待(python3中会好很多)

当你使用string类型时,实际上会储存一个字节串

解码字节流

你可以把字节流解码(decode)成一个Unicode对象,把一个Unicode 对象编码(encode)为字节流

你最好是尽早的将字节流解码为Unicode(字节流进入程序的时候)

你不能简单地输出一个Unicode对象。它必须在输出前被变成一个字节串

str/unicode

在mac下python2.7.5

# unicodeunicode_a=u"你好"type(unicode_a)# unicode_a# u'\u4f60\u597d'unicode_b=u'\u4f60\u597d'unicode_b# u'\u4f60\u597d'unicode_a==unicode_b# True# unicode_c = unicode("你好") python2会报错,python会把所有东西作为字节流理解u'hello'==unicode("hello")#  True,如果unicode_a.encode("utf-8")# '\xe4\xbd\xa0\xe5\xa5\xbd'################# strstr_a="你好"str_a# '\xe4\xbd\xa0\xe5\xa5\xbd'str_a.decode("utf-8")# u'\u4f60\u597d'str_a.decode("utf-8")==u"你好"# True

__repr__的目标是准确性,__str__的目标是可读性

codecs模块

codecs模块能在处理字节流的时候提供很大帮助。你可以用定义的编码来打开文件并且你从文件里读取的内容会被自动转化为Unicode对象。

读写文件

当从一个文件读取数据的时候,codecs.open 会创建一个文件对象能够自动将utf-8编码文件转化为一个Unicode对象,而写入文件这样写:

importcodecsfh=codecs.open("/tmp/utf-8.txt","w","utf-8")fh.write(u"\u2013")fh.close()

使用urllib流

stream=urllib.urlopen("http://www.google.com")Reader=codecs.getreader("utf-8")fh=Reader(stream)type(fh.read(1))# ,应该尽可能让程序内部的数据都是

你必须对codecs模块十分小心。你传进去的东西必须是一个Unicode对象,否则它会自动将字节流作为ASCII进行解码。

策略

python编解码涉及的问题可能很多,上至大神下至小白,都可能受扰,为了保持简单,我们可以保持这样一种习惯:关注输入输出,内部保持unicode。

每当有数据进入程序,将其解码(decode)为unicode(utf-8)

当有数据从程序中输出时,将其编码(encode)为utf-8

最佳实践:

最先解码(解码为unicode对象),最后编码(输出为字节码)

最先解码意味着无论何时有字节流输入,需要尽早将输入解码为Unicode

最后编码意味着只有你打算将文本输出到某个地方时,才把它编码为字节流。这个输出可能是一个文件,一个数据库,一个socket等等

默认使用utf-8编码

使用codecs和Unicode对象来简化处理

codecs模块能够让我们在处理诸如文件或socket这样的流的时候能少踩一些坑。如果没有codecs提供的这个工具,你就必须将文件内容读取为字节流,然后将这个字节流解码为Unicode对象。

codecs模块能够让你快速的将字节流转化为Unicode对象,省去很多麻烦。

linux下的一些工具

file

file命令用来探测给定文件的类型,

参数:

-i:显示MIME类别。

-c:详细显示指令执行过程,便于排错或分析程序执行的情形;

file *

iconv

conv命令是用来转换文件的编码方式的,比如它可以将UTF8编码的转换成GB18030的编码

iconv -f encoding -t encoding inputfile

iconv -f UTF-8 -t GBK file1 -o file2 //将一个UTF-8 编码的文件转换成GBK编码

chardet

有时候我们不知道文件/字节流采用了什么编码,可以让chardet来猜测编码,chardet是python的一个库

传输编码语法(transfer encoding syntax)

用于处理上一层次的字符编码方案提供的字节序列。一般其功能包括两种:一是把字节序列的值映射到一套更受限制的值域内,以满足传输环境的限制,例如Email传输时Base64或者quoted-printable,都是把8位的字节编码为7位长的数据;另一是压缩字节序列的值,如LZW或者进程长度编码等无损压缩技术。

BASE64编码

Base64常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据

常用于在URL、Cookie、网页中传输少量二进制数据。

所谓Base64,就是说选出64个字符----小写字母a-z、大写字母A-Z、数字0-9、符号"+"、"/"(再加上作为垫字的"=",实际上是65个字符)----作为一个基本字符集。然后,其他所有符号都转换成这个字符集中的字符。

关于base64更多的细节可以参考维基百科和Base64笔记

在python中实现

importbase64base64.b64encode('hello')#aGVsbG8=  , 被编码的不是应该是二进制数据吧,python的二进制默认被解析为ascii?,在这里hello无论是b'hello'还是'hello'/u'hello',结果都一样base64.b64decode("aGVsbG8=")# helloa=u'你好'# \u4f60\u597db=base64.b64encode(a.encode("utf-8"))#5L2g5aW9c=base64.b64decode(b)# \xe4\xbd\xa0\xe5\xa5\xbdc.decode("utf-8")# u'\u4f60\u597d'# 由于标准的Base64编码后可能出现字符+和/,在URL中就不能直接作为参数,所以又有一种"url safe"的base64编码,其实就是把字符+和/分别变成-和_d=u"哈里谢顿".encode("utf-8")# \xe5\x93\x88\xe9\x87\x8c\xe8\xb0\xa2\xe9\xa1\xbfbase64.b64encode(d)# 5ZOI6YeM6LCi6aG/ , 有反斜杠e=base64.urlsafe_b64encode(d)# 5ZOI6YeM6LCi6aG_base64.urlsafe_b64decode(e)# \xe5\x93\x88\xe9\x87\x8c\xe8\xb0\xa2\xe9\xa1\xbf

url中的编码问题

一般而言使用urllib库中的urlencode函数就好了

fromurllibimporturlencodedata={'name':'小明',#u'小明'则需要encode为字节码'age':'10岁'}printurlencode(data)# age=10%E5%B2%81&name=%E5%B0%8F%E6%98%8E#仅对字符串进行转码可以使用quotefromurllibimportquotequote('小明')#%E5%B0%8F%E6%98%8E'

如果有大量此类工作可以考虑使用furl

在线工具

在线编码转换

UrlEncode编码/UrlDecode解码

Unicode编码转换:还包括unix时间戳

一些细碎知识

Windows简体中文版中,ANSI是默认的编码方式。对于英文文件是ASCII编码,对于简体中文文件是GB2312编码(繁体中文版会采用Big5码)

python中字节流和unicode的代码视角比较

stackoverflow Python unicode equal comparison failed

参考

字符编码

十分钟搞清字符集和字符编码

10分钟学会理解和解决MySQL乱码问题

字符编码笔记:ASCII,Unicode和UTF-8

Python编码和Unicode

Python: 熟悉又陌生的字符编码

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容