python学习笔记
起因:
#!\user\bin\python
#-*-coding:utf-8-*-
import urllib.request
import gzip
def unzip(old_data):
try:
new_data=gzip.decompress(old_data).decode('utf-8')
except:
new_data=old_data.decode('utf-8')
return new_data
def spider():
url='http://www.zhihu.com/'
headers={
'Accept-Encoding':'gzip,deflate',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Trident/7.0; rv:11.0) like Gecko'}
req=urllib.request.Request(url=url,headers=headers)
conn=urllib.request.urlopen(req)
source=unzip(conn.read())
print(source)
if __name__=='__main__':
spider()
运行结果:
ERROR:
Traceback (most recent call last):
File "E:\pythonExample\spider2.py", line 24, in <module>
spider()
File "E:\pythonExample\spider2.py", line 21, in spider
print(source)
File "C:\Program Files (x86)\Python35-32\lib\encodings\cp1252.py", line 19, in encode
return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode characters in position 239-247: character maps to <undefined>
[Finished in 16.4s with exit code 1]
[shell_cmd: python -u "E:\pythonExample\spider2.py"]
[dir: E:\pythonExample]
[path: C:\Program Files (x86)\Python35-32\Scripts\;C:\Program Files (x86)\Python35-32\;C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\Java\jdk1.8.0_65\bin;C:\Program Files\Java\jdk1.8.0_65\jre]
多番查询后,发现是爬回来的内容带有中文导致。
这个程序本身是没问题的。主要是print 函数输出到sublime 终端的时候的编码导致
通过
import sys
print(sys.stdout.encoding)
可以看到输出:cp1252
说明:
python在编译运行源码后,默认将输出结果以cp1251编码,发送给Sublime Text。但是结果有中文,所以这个编码是无法对内容进行解析(编码)的。。。
当我把本地的system locale 改为Chinese后(步骤见博客命令无法输入中文),发现sys.stdout.encoding变成了cp936(GBK).现在可以对内容进行cp936编码,然后发送给sublime.但是新的错误出现了。
Decode error - output not utf-8
原因在于Sublime Text 中python build的默认接收编码是UTF-8。Sublime Text在接收到python输出后,试图以utf-8解码cp936编码的流。当cp936编码的流中没有汉字时,因为英文字符集在cp936和utf-8中的编码兼容,所以用utf-8解码不会出错;当 cp936编码的流中 有汉字时,因为汉字字符集在cp936与utf-8的编码不兼容,所以用utf-8解码就会错误。
解决:我用方法2解决的。。
方法1. Python有个PythonIoEncoding环境变量,用来定义stdin/stdout/stderr的编码。
windows下,cmd中执行python -h 可以看到该环境变量的说明。
所以可以在环境变量下,添加一个环境变量pythonioencoding,值为utf-8,即可解决该问题。
方法2.修改Sublime Text的python build的设置。将其编码设置为cp936。
sublime tools–>build system –>new system
输入
{
"cmd": ["python", "-u", "$file"],
"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
"selector": "source.python","encoding":"cp936"
}
保存为Python.sublime-package,重启sublime
参考:http://www.th7.cn/Program/Python/201411/319372.shtml
文献是从sys.stdout.encoding变成cp936后的解释,前面sys.stdout.encoding为cp1252时出现encode error的原因是结合这篇文章进行的猜想。
后记:
某天发现了这样的设置
{
"cmd": ["python", "-u", "$file"],
"file_regex": "^[ ]*File "(...*?)", line ([0-9]*)",
"env": {"PYTHONIOENCODING": "utf8"},
"selector": "source.python“,
"shell":"true"
}