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进行解码得到的结果,将无法还原原来的字符串内容

具体可参见python encode和decode函数说明

个人经验

用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:

  1. UNICODE,GBK,UTF-8区别 http://www.cnblogs.com/cy163/archive/2007/05/31/766886.html
  2. python编码的意义 https://segmentfault.com/a/1190000004166137
  3. https://segmentfault.com/q/1010000004620523
  4. http://stackoverflow.com/questions/3218014/unicodeencodeerror-gbk-codec-cant-encode-character-illegal-multibyte-sequen
  5. python encode和decode函数说明 http://www.cnblogs.com/evening/archive/2012/04/19/2457440.html

Encode的更多相关文章

  1. 防御XSS攻击-encode用户输入内容的重要性

    一.开场先科普下XSS 跨站脚本攻击(Cross Site Scripting),为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS.恶 ...

  2. HttpPost过程中使用的URLEncoder.encode(something, encode)

    URLEncoder.encode("刘美美", "utf-8").toString()       =     %E5%88%98%E7%BE%8E%E7%B ...

  3. [LeetCode] Encode String with Shortest Length 最短长度编码字符串

    Given a non-empty string, encode the string such that its encoded length is the shortest. The encodi ...

  4. [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 ...

  5. 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'))

  6. javascript处理HTML的Encode(转码)和Decode(解码)总结

    HTML的Encode(转码)和解码(Decode)在平时的开发中也是经常要处理的,在这里总结了使用javascript处理HTML的Encode(转码)和解码(Decode)的常用方式 一.用浏览器 ...

  7. URLEncoder.encode 和 URLDecoder.decode 处理url的特殊参数

    在使用 url 的 queryString 传递参数时,因为参数的值,被DES加密了,而加密得到的是 Base64的编码字符串,类似于: za4T8MHB/6mhmYgXB7IntyyOUL7Cl++ ...

  8. Python3的decode()与encode()

    python3的decode()与encode() Tags: Python Python3 对于从python2.7过来的人,对python3的感受就是python3对文本以及二进制数据做了比较清晰 ...

  9. 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 ...

  10. 字符编码和python .encode().decode()方法

    字符编码与encode.decode的问题:  用8个开关表示世界万物   ASCII :  American Standard Code for Information Interchange,美国 ...

随机推荐

  1. Scrapy框架: 通用爬虫之XMLFeedSpider

    步骤01: 创建项目 scrapy startproject xmlfeedspider 步骤02: 使用XMLFeedSpider模版创建爬虫 scrapy genspider -t xmlfeed ...

  2. java异常不匹配问题

    java的异常处理是为了提高程序健壮性的. 当发生异常的时候,我们把这个异常捕获到,或者throw出去.然后对这些异常的情况进行处理.并且异常发生之后的代码仍然会执行,这样就能提高程序的健壮性.如下 ...

  3. Java8 LocalDate操作时间和日期的API

    时间项目中的涉及到的时间处理非常多,犹豫SimpleDateFormat的不安全性以及Calendar等类在计算时比较复杂, 往往我们都会使用工具类来封装较多的日期处理函数, 但是JDK8中新增了操作 ...

  4. 灵活轻便的Table控件,适合复杂样式的内容排版

    github仓库地址 https://github.com/gaoyangclub/GYTableViewController 前言 TableView是在项目开发的时候经常用到的组件,几乎百分之八十 ...

  5. Nginx的应用之虚拟主机

    开始前请确保selinux关闭,否则当配置完虚拟主机后,尽管权限或者网站目录都正确,访问的结果也是403 nginx的虚拟主机有三种方式: 一.基于域名的虚拟主机 (1)创建对应的web站点目录以及程 ...

  6. Docker部署Flask应用

    创建应用 首先,编写一个简单的Flask应用:docker_test/flask_app.py Docker 安装 请根据自己的操作系统自行安装. Docker简介 Docker 镜像 Docker镜 ...

  7. MySQL-事件总结

    是什么?事件是一组SQL集合,简单说就是mysql中的定时器,时间到了就执行. 一:查询事件变量,如果查询不到变量,说明数据库版本过低,不支持事件. SHOW VARIABLES LIKE 'even ...

  8. Ubuntu修改用户和root密码

    如果要修改root的密码:sudo passwd 如果要修改_当前_用户的密码:passwd 如果要修改其他用户的密码(你得有权限):sudo passwd USERNAME,USERNAME就是你要 ...

  9. 5. zabbix服务端添加fping

    zabbix服务端添加fping 原文链接:http://blog.chinaunix.net/uid-23500957-id-4366928.html fping-3.15.tar.gz 包的路径D ...

  10. PostgreSQL的约束

    约束类型:检查约束.非空约束.唯一约束.主键.外键 1.  检查约束 设置某个字段里的数值必须满足约束表达式的条件. 例:限制人的年龄在0~120之间,语句如下: create table perso ...