@Alston
2017-06-07T23:11:35.000000Z
字数 1675
阅读 2612
python量化
(注:如无特殊说明,本文所指Python均为Python3.5+)
学习Python的同学们应该都知道,编码问题是编程中遇到最广泛的问题了,尤其是需要处理中文的时候。比如如果去爬一个中文网站,好死不死用了lxml.etree模块,又好死不死用了fromstring来构造节点。那经常就会出问题。举个例子:
from lxml import etreetext = '<body><p>你好</p></body>'html = etree.fromstring(text)result = etree.tostring(html,pretty_print=True)print(result)print(result.decode('utf-8'))
输出为byte型:
b'<body>\n <p>你好</p>\n</body>\n'<body><p>你好</p></body>
可以看到你好变成了乱码你好。当然如果了解编码的话就知道这其他不是乱码,而是汉字对应的的utf-8编码后的字节,只不过是用十进制表示的并加上了 &# 前缀以及 ; 后缀。(这里之所以是utf-8是因为Python3里默认以utf-8编码处理字符串)。
当然,这里只是举个例子以便引入本篇主题。针对lxml,解决的办法有很多,比如不要用fromstring来构造节点,改用etree.HTML()来构造;或者在使用tostring的时候,加上编码,在输出的时候再decode一下,具体如下:
result = etree.tostring(html, encoding="utf-8", ...pretty_print=True)print(result.decode('utf-8'))`
甚至,你完成可以不用lxml,改用大家都在用的BeautifulSoup甚至是pyquery。这是后话。今天主要还是讲一讲python的编码问题。
Python3跟Python2最大的不同在于,Python3中默认使用utf-8作为字符串。所以你可以直接使用print("你好世界")来输出中文,而不需要像Python2一样使用print u"你好世界"来说明编码。
而在Python内部,字符串都是以unicode编码储存的(字节流),只有在print输出的时候才转换成各种不同的编码。
所以一般在进行编码转换的时候,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码decode的作用是将其他编码的字符串转换成unicode编码,如str1.decode('gb2312'),表示将gb2312编码的字符串str1转换成unicode编码。 encode的作用是将unicode编码转换成其他编码的字符串,如str2.encode('gb2312'),表示将unicode编码的字符串str2转换成gb2312编码。(摘自推酷)
可以参考上面那个例子,tostring(encoding='utf-8')表示将tostring生成的字符串按"utf-8"编码encode成unicode,result.decode('utf-8')表示再把unicode按"utf-8"编码decode成可以用于输出的字符串格式。图解如下:
另外一个非常好的习惯是在代码文件开头注明编码:
#-*- coding:utf-8 -*-
或者用sys模块的setdefaultencoding函数,当然,python解释器在启动的时候会进行一些处理,无法直接使用这个函数,得先reload,比较麻烦,也比较危险,所以最好不要用这个方法吧。