Encode
by kinsly
本文的内容均基于python3.5
编码一直是python中的大坑,反正我是一直没搞明白,今天在做爬虫的时候,觉得实在是有必要把这些东西整理一下。
什么是编码
简单的来说就是,为了是计算机能够表达不同的文字,人们制定了一些表达字母符号的方法,常见的编码有ASCII,utf-8,汉字常见的有GBK,big5, GB18030。也就是说字符必须编码后才能被计算机所处理,计算机使用的缺省编码方式也就是计算机的内码。具体细节参见UNICODE,GBK,UTF-8区别
Unicode
Unicode是国际组织设计的,包括了世界上所有语言文字的编码方案。那么Unicode只是一种编码方案,并没有规定如何传输,保存编码。所以这就是为什么我们有UTF-8,UTF-7,UTF-16,这几种都是按照unicode设计,不同的具体编码方案。为什么UTF-8是比较常见的呢,是因为UTF-8与ISO-8859-1完全兼容。世界上有两个设计unicode的组织,一个是软件制造商协会,另一个是ISO,所以UTF-8好在能够兼容两个协会的标准。UTF-8是以8位为单元对UCS进行编码。
内码
windows目前已经支持unicode,但是很多文档和程序都是采用特定编码系统。所以我们在使用某些软件的时候,必须将unicode转化为软件支持的编码。如word只支持gb2312,但是好像也能识别unicode。所以如果想输出csv然后用word打开,需要转化为GBK或者GB18030,或者BOMUTF-8。BOM的意思是 Byte order Mark
Python 遇到的问题
UnicodeDecodeError: 'charmap' codec can't decode byte X in position Y: character maps to $<$undefine$>$
这个问题一般来说是在输出的时候,没有对输出的内容进行encode,也就是说计算机内部存储的是unicode,而你需要对其进行encode。
data_df.to_csv('some2.csv',encoding='gb18030')
或者是当你读取unicode保存的文件的时候,如json,你也需要对其进行转码。
with open('a.json',encoding="utf-8") as data_file:
data = json.load(data_file)
UnicodeEncodeError: 'gbk' codec can't encode character '\ufeff' in position 10: illegal multibyte sequence
这种问题往往是你确定的这种编码方式不能识别数据中的某些编码,也不一定是都识别不了,这时可以换一种编码方式,如GB18030之类的
TypeError: a bytes-like object is required, not 'str'
这个好像是,在读写的时候,要把str转化成编码,也就是二进制之类的,需要进行decode
TypeError: Expected String or Unicode
在用pandas读取json会出现,也可能是没有encoding的问题
设置默认encoding方式
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
在python2.7有这样的用法,但是由于有些包默认不一定是utf-8,所以最好还是不要这样写。
核心三原则
- 因为某些原因, python 打开流读取出的是str,所以用你知道的每一种编码把它解码成unicode
- 大概是因为同样的原因,python 的输出也是str, 但是任何一个unicode 只有到要输出的时候才编码成str
- 在此之间,放弃该死的str,忘了它,当你开始处理的时候,确保你的每一个字符串对象都是unicode
这是segmentfault上一篇文章上说的,感谢作者。题目是python编码的意义
不过好像python3已经没有了这种问题
你导入的好几个模块我都没用过....不过能看出来是跳进了python2的encoding大坑了-_-
总之,研究了近百篇文章后我才意识到,破解encoding问题不用那么复杂.
不用''.encode().decode(),也不用sys.setdefaultencode之类
只要你在全文里除了最后输出部分,保证其余每一个字符串全都是unicode格式就行了.
比如直接手写的字符串你好,就要写成u'你好'
在比如,合并数组为字符串时, 就u''.join(arr)
其余的就unicode(s)
最后实在不行了才.decode().encode()
至于codex模块和charset, ccharset等检测字符串编码的,遇到中文一样傻眼,劝别试.
看到另一个回答,这样说,其实也挺有道理,就是不想太纠结,就不要搞太复杂。简单粗暴
decode & encode
通常我们需要decode()与encode()来进行解码与编码
decode encode
str ---------> unicode ---------->str
在python2中,编码之间的转换需要通过unicode,所以假如你想将由gbk编码的字符串转换为utf-8编码,需要先将其转换为unicode,再将其转换为utf-8编码的字符串
u = u'中文' #显示指定unicode类型对象u
str = u.encode('gb2312') #以gb2312编码对unicode对像进行编码
str1 = u.encode('gbk') #以gbk编码对unicode对像进行编码
str2 = u.encode('utf-8') #以utf-8编码对unicode对像进行编码
u1 = str.decode('gb2312')#以gb2312编码对字符串str进行解码,以获取unicode
u2 = str.decode('utf-8')#如果以utf-8的编码对str进行解码得到的结果,将无法还原原来的unicode类型
而在python3中,取消了unicode类型,代替它的是使用unicode字符的字符串类型(str),也就是说,上面的说明可以转化为下面这种形式
decode encode
bytes ---------> str(unicode)------------>bytes
u = '中文' #指定字符串类型对象u
str = u.encode('gb2312') #以gb2312编码对u进行编码,获得bytes类型对象str
u1 = str.decode('gb2312')#以gb2312编码对字符串str进行解码,获得字符串类型对象u1
u2 = str.decode('utf-8')#如果以utf-8的编码对str进行解码得到的结果,将无法还原原来的字符串内容
个人经验
用pandas的函数,
df.to_csv('a.csv', encoding='gbk')
可能会方便一点。或者
df.to_csv('a.csv', encoding='gbk',mode = 'a')
这样可以接着写,类似于append的功能
当然也可以直接csv包中的函数直接保存
with open('m.csv','w',encoding = 'utf-8') as f:
writer = csv.writer(f)
for i in range(1,len(data_total)):
writer.writerow(data_total)
但是这样存储出来的csv用word打开可能是乱码。这时候可以用记事本将其打开,另存为的时候将其编码格式修改为unicode,这样我的word就能识别这些数据
致谢:谢谢汪老师在这个过程之中的帮助。
reference:
- UNICODE,GBK,UTF-8区别 http://www.cnblogs.com/cy163/archive/2007/05/31/766886.html
- python编码的意义 https://segmentfault.com/a/1190000004166137
- https://segmentfault.com/q/1010000004620523
- http://stackoverflow.com/questions/3218014/unicodeencodeerror-gbk-codec-cant-encode-character-illegal-multibyte-sequen
- python encode和decode函数说明 http://www.cnblogs.com/evening/archive/2012/04/19/2457440.html
Encode的更多相关文章
- 防御XSS攻击-encode用户输入内容的重要性
一.开场先科普下XSS 跨站脚本攻击(Cross Site Scripting),为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS.恶 ...
- HttpPost过程中使用的URLEncoder.encode(something, encode)
URLEncoder.encode("刘美美", "utf-8").toString() = %E5%88%98%E7%BE%8E%E7%B ...
- [LeetCode] Encode String with Shortest Length 最短长度编码字符串
Given a non-empty string, encode the string such that its encoded length is the shortest. The encodi ...
- [LeetCode] Encode and Decode Strings 加码解码字符串
Design an algorithm to encode a list of strings to a string. The encoded string is then sent over th ...
- UnicodeEncodeError: 'ascii' codec can't encode characters in position 820-823: ordinal not in range(128)
真是奇怪了,在itermi里 print(data) 就能直接运行,而在sublime里,就非得写成这样 print(data.encode('utf-8'))
- javascript处理HTML的Encode(转码)和Decode(解码)总结
HTML的Encode(转码)和解码(Decode)在平时的开发中也是经常要处理的,在这里总结了使用javascript处理HTML的Encode(转码)和解码(Decode)的常用方式 一.用浏览器 ...
- URLEncoder.encode 和 URLDecoder.decode 处理url的特殊参数
在使用 url 的 queryString 传递参数时,因为参数的值,被DES加密了,而加密得到的是 Base64的编码字符串,类似于: za4T8MHB/6mhmYgXB7IntyyOUL7Cl++ ...
- Python3的decode()与encode()
python3的decode()与encode() Tags: Python Python3 对于从python2.7过来的人,对python3的感受就是python3对文本以及二进制数据做了比较清晰 ...
- Leetcode: Encode String with Shortest Length && G面经
Given a non-empty string, encode the string such that its encoded length is the shortest. The encodi ...
- 字符编码和python .encode().decode()方法
字符编码与encode.decode的问题: 用8个开关表示世界万物 ASCII : American Standard Code for Information Interchange,美国 ...
随机推荐
- create Excel file - snippet
http://www.codepal.co.uk/show/Line_breaks_lost_and_br_tags_show_when_exporting_to_Excel_file Protec ...
- Loadrunner实现多台测试机负载时可能遇到的难题
压测机安装的loadrunner版本为11.0 压测机器的操作系统是windows server 2016 所有的负载机器操作系统和压侧机器是一样的,都是windows server 2016 Err ...
- 45-python基础-python3-字符串-常用字符串方法(三)-startswith()-endswith()
4-字符串方法 startswith()和 endswith() startswith()和 endswith()判断字符串是否以某个字符串开始或结尾,存在返回 True,否则,方法返回 False. ...
- WPF 的二维绘图(二)——几何图形Geometry
<本文转自同行> 在WPF的DrawingContext对象中,提供了基本的绘制椭圆和矩形的API:DrawEllipse和DrawRectangle.但是,这些是远远不够用的,我们在日常 ...
- 2019-9-29-dotnet-对-DateTime-排序
title author date CreateTime categories dotnet 对 DateTime 排序 lindexi 2019-09-29 14:55:49 +0800 2019- ...
- Linux中各类程序的配置文件位置
目录 Linux中各类程序的配置文件位置 1.启动引导程序配置文件 2.系统启动文件核脚本 3.网络配置文件 4.超级服务程序配置文件和目录 5.硬件配置 6.硬件访问文件 7.扫描仪配置文件 8.打 ...
- go语言从例子开始之Example27.超时处理
超时 对于一个连接外部资源,或者其它一些需要花费执行时间的操作的程序而言是很重要的.得益于通道和 select,在 Go中实现超时操作是简洁而优雅的. Example: package main im ...
- python-django_rest_framework中的request/Response
rest_framework中的request是被rest_framework再次封装过的,并在原request上添加了许多别的属性: (原Django中的request可用request._requ ...
- sql developer 中文乱码解决办法
近日在fedora13中安装了oracle和sql developer,在英文环境下启动sql developer正常,可是切换到中文环境下就显示乱码.google了一下,确定是因为JDK不支持中文的 ...
- Python中的try-finally
>>> try: ... raise KeyboardInterrupt ... finally: ... print('Goodbye, world!') ... Goodbye, ...