Python的解码和编码
使用Python语言做网络爬虫或者写自动化脚本时,总会遇到“中文乱码”的问题,很是头疼。很多“中文乱码”的问题是跟Python的解码/编码有关,所以今天和大家说说Python的解码/编码(以Python2.7为例)。
1.什么是Python解码/编码?
Python里面的解码和编码也就是unicode和str这两种形式的相互转化。解码就是str -> unicode,相反的,编码是unicode -> str。
总的来说就是:unicode是Python解释器的内码,所有代码文件在导入并执行时,Python解释器会先将字符串使用你指定的编码形式解码成unicode,然后再进行各种操作。不管是对字符串的操作,还是正则表达式,还是读写文件等等最好都通过unicode来进行。
Python解释器在导入Python代码文件并执行时,会先查看文件头有没有编码声明(例如# -*- coding: utf-8 -*-等)。如果发现声明,如# -*-coding: utf-8 -*-,会将文件中的字符串从utf-8先解释成unicode的形式;如果文件头没有编码声明,则会以默认的ASCII来解释成unicode的形式。
2.解码函数decode()和编码函数encode()
在Python中,解码函数是decode(),编码函数是encode()。
﹒decode()的作用是将其他编码的字符串转换成unicode 格式,例如:name.decode(“utf-8”),表示将utf-8编码的字符串name转换成unicode
﹒encode()的作用是将unicode编码转换成其他编码的字符串,例如:
name.encode(“GB2312”),表示将GB2312编码的字符串name转换成GB2312
当代码中同时有编码声明(例如# -*- coding: utf-8 -*-等)和编码函数encode(‘gbk’),Python在执行时会优先选择真实编码gbk。当存在encode(‘gbk’)时,即便在开头申明了#-*- coding: utf-8 -*-,没有指定解码方式,程序是会报错的。
解决方案:在中文“哈哈”前加上字符“u”,直接使字符是unicode类型,不用再将“哈哈”去解码操作。
注意:上图中的 'xb9xfexb9xfe'是“哈哈”的gbk编码;'xe5x93x88xe5x93x88'是“哈哈”的utf-8编码。上图说明,当存在encode(‘gbk’)时,即便在开头申明了#-*- coding: utf-8 -*-,在执行时会优先选择encode()函数中的gbk编码方式。
需要注意的一点是,假设stra=‘哈哈’,如果我们调用stra.encode(),这里涉及到一个隐士的类型转化,会先将stra转化成unicode,才能进行编码,这也是不太容易理解的地方。而在中文前添加“u”字符,就使得stra转化成unicode这一步略去。
3.Python解码
解码是Python自动进行的,我们在程序开头没有编码声明(如:#-*-coding:utf-8-*-),也没有指明解码方式,Python就会使用sys.defaultencoding指明的方式来解码。很多情况下sys.defaultencoding是ASCII。
4.Python编码
Python默认采用ASCII编码,而ASCII编码不能用来编码中文字符。举个简单的例子:
如下图,运行脚本时会有提示。因为Python编码默认是ASCII编码,不支持中文。
解决方案1:在文件开头输入支持中文的编码方式:# -*- coding: gbk -*-。
解决方案2:Python2.x默认是不支持中文的,我们在程序的开头加上#-*-coding:utf-8-*-,并在中文前加上“u”字符,也可以解决这个问题。这里的“u”表示将后面跟的字符串以unicode格式存储,然后Python会根据程序第一行的utf-8编码识别代码中的中文“你好”,然后转换成unicode对象(重申一下:中文前加“u”,直接免去“将字符串解码成unicode”这一步的操作哦)。
补充一点:如果在中文前没有添加“u”,仅仅在程序的开头加上#-*-coding:utf-8-*-,屏幕上打印出的不是“你好”,如下图。这是由于Python编码与控制台编码的不一致造成的。Windows下控制台中的编码使用的是gbk,而在代码中使用的utf-8,Python按照utf-8编码打印到gbk编码的控制台下自然就会不一致而不能打印出正确的汉字。
总之,在Python2.x版本中使用中文,最好在程序开头添加一行声明文件编码的注释:#-*-coding:utf-8-*-,然后在中文前添加“u”字符。可以不使用解码、编码函数,就尽量别使用(真的会绕晕的,哈哈……)。
原创文章,仅代表非比君个人观点,说的不一定是对的,欢迎大家指正。
用微信添加 非比测试 公众号即可订阅。转载请保留作者、公共账号信息,内容必须与本文保持严格一致,不得修改/替换/增减本文包含的任何文字,不得擅自增加小标题、引语、摘要等。本公众号一切内容禁止摘编、衍生及演绎。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 告别传统工业互联网,提高数字管控思维:三维组态分布式能源站
- 爱奇艺iOS移动端网络优化实践:请求成功率优化
- Java数据类型
- Python爬虫之scrapy构造并发送请求
- Python爬虫之scrapy模拟登陆
- Python爬虫之scrapy中间件的使用
- Python爬虫之scrapy_redis原理分析并实现断点续爬以及分布式爬虫
- Python爬虫之scrapy_splash组件的使用
- Python爬虫之scrapy的日志信息与配置
- Python爬虫之scrapyd部署scrapy项目
- 最近发现一个很有趣的随机小姐姐视频源码 分享给大家
- Codeforces Round #633 (Div. 2)C Powered Addition (贪心,二进制)
- Spring 整合 JUnit
- Java Stax解析XML示例
- Codeforces Round #633 (Div. 2) B Sorted Adjacent Differences(直观感知+排序插放)