在学习requests库爬取网页的时候,出现了“解决Python2.7的UnicodeEncodeError: ‘ascii’ codec can’t encode异常错误”的错误。
# -*-coding:utf-8-*- import requests from bs4 import BeautifulSoup import bs4 def getHTMLText(url): try: r = requests.get(url, timeout=30) r.raise_for_status() r.encoding = r.apparent_encoding return r.text except: return '' def fillUnivList(ulist, html): soup = BeautifulSoup(html, 'html.parser') for tr in soup.find('tbody').children: if isinstance(tr, bs4.element.Tag): tds = tr('td') ulist.append([tds[0].string, tds[1].string, tds[2].string]) def printUnivList(ulist, num): print('{:^10}\t{:^6}\t{:^10}'.format('range', 'University', 'score')) for i in range(num): u = ulist[i] print('{:^10}\t{:^6}\t{:^10}'.format(u[0], u[1], u[2])) # print('Suc'+str(num)) def main(): uinfo = [] url = 'http://www.zuihaodaxue.cn/zuihaodaxuepaiming2018.html' html = getHTMLText(url) fillUnivList(uinfo, html) printUnivList(uinfo, 20) #main() if __name__ == '__main__': main()
代码上面应该没有什么问题,Python使用的是版本2.7,但是在运行的时候出现了异常错误UnicodeEncodeError,输出结果:
从出错原因来看,大致是因为编码的问题,因为输出的内容中有中文,Unicode嘛与ASCII码不兼容,由于这个脚本使用的是utf-8编码的,但是python的默认编码方式为Ascii码,可以通过以下命令进行查询:
>>> import sys >>> print sys.getdefaultencoding() ascii
因为Ascii的范围为0-128,默认为Ascii,故而python在处理的时候自然调用Ascii码进行处理,因此在处理汉字的时候就超出了Ascii的范围,从而抛出ordinal not in range的异常错误。
那如何修改呢?
通过修改默认额编码方式,即修改 setdefaultencoding
import sys sys.setdefaultencoding('utf-8')
但是 setdefaultencoding 就是 sys 的方法,其实是这里的 sys.setdefaultencoding('utf-8')没有生效的原因,因为在python27/Lib/目录下,在site.py文件中:
# Remove sys.setdefaultencoding() so that users cannot change the # encoding after initialization. The test for presence is needed when # this module is run as a script, because this code is executed twice. if hasattr(sys, "setdefaultencoding"): del sys.setdefaultencoding
为什么要查看site.py文件呢,因为在加载python模块的时候,会加载site.py模块
C:\Users\rhx>python -v # installing zipimport hook import zipimport # builtin # installed zipimport hook # C:\Python27\lib\site.pyc matches C:\Python27\lib\site.py
因此第一次导入后,再次sys.setdefaultencoding执行的时候会被删除,所以需要重新导入一次 reload(os)。明白原理之后,这样就有两种方式设置python的默认编码了。
1、设置为 utf-8 的编码格式
import sys reload(sys) sys.setdefaultencoding('utf8')
2、在python的Lib\site-packages文件夹下新建一个sitecustomize.py,内容为
# encoding=utf8 import sys reload(sys) sys.setdefaultencoding('utf8')
此时重启python解释器,执行sys.getdefaultencoding(),发现编码已经被设置为utf8的了,多次重启之后,效果相同,这是因为系统在python启动的时候,自行调用该文件,设置系统的默认编码,而不需要每次都手动的加上解决代码,属于一劳永逸的解决方法。
这样在模块的开始部分加入以上设置即可。