python编码问题的最终分析

时间:2022-12-16 15:20:54

python初学者,往往因为字符编码的问题而苦恼不已,本人也是阅读了大量的博客,再进行了一定的测试,基本搞清楚了编码问题的前因后果。下面一段代码是在python3.5上的,以它为例进行讲解(请忽略糟糕的变量名)。

 #!/usr/bin/env python
 # -*- coding:utf-8 -*-

 import re
 import urllib.request

 def get_html(url):
     download_page = urllib.request.urlopen(url).read().decode('GBK')
     return download_page

 def get_image(html):
     img_list = re.findall(r'src="(.+?\.jpg)"', html)
     x = 1
     for img_url in img_list:
         print("正在下载" + str(x) + "")
         urllib.request.urlretrieve("https:" + img_url.lstrip(), 'd:\\list\\%s.jpg' % x)
         x += 1

 html_page = get_html("https://mm.taobao.com/self/aiShow.htm?spm=719.7763510.1998643336.43.xMxXj5&userId=722569871")
 get_image(html_page)

这是一个很简单的网络图片爬虫,代码本身并没有什么特色和难点。我们主要关注的是编码问题。由于是python3.5的环境,代码第二行可以没有。


网上多数文章都没有清晰的指出一个问题:编码问题分“代码的编码”和“网页或文件的编码”。什么意思?就是在写代码时要同时考虑代码本身的编码和你的代码要处理的网页或文件对象的编码!这是两个方面,不能混淆!


  1、先来说说代码的编码:

代码的编码指的是你用vim、notepad、UE、IDE等等文本编辑工具或集成环境,通过键盘输入字符,并保存成文件储存在硬盘的东西。在以往python2.x版本的时候,默认使用ASCII码,它使用一个字节也就是8位空间,只存储127个英文系字母/字符,通俗的讲,它只支持英语,不支持中文。因此,如果在代码里输入中文,编译会报错,我们往往采取在代码文件第二行顶头进行编码声明的方式来解决这个问题,也就是#coding:utf-8。通过这一行,就指定了代码文件里的所有字符都使用utf-8的编码格式进行存储,而在utf-8里是支持中文的,也就是说,你可以直接这样:name=‘jack’ 和 name2= '张三'。而在python3.x版本中,unicode编码成为了默认编码,unicode也是一个同时支持英文和中文的编码格式,因此你连第二行的编码申明都可以不用了,直接使用中文就好了。

  但是,#coding:utf-8解决不了你在处理网页和数据文件中的编码问题,它只针对代码本身!

  2、再说说网页或文件对象的编码:

  在python代码中,处理网页和文件系统上的数据文件,是再正常不过的事了,比如各种爬虫,比如文件读取。上面我们解决了代码自己的编码,但是并没有解决处理对象的编码!什么意思?以文章开头的代码为例,它用来爬取一个网页的图片,而这个网页是用GBK编码的(这是一种中文编码方式)。可以通过查看页面源代码得知。

python编码问题的最终分析

  页面被读取后,以GBK编码格式暂存在内存。但是,内存里处理字符都是用unicode编码格式的!这就存在了问题。

python编码问题的最终分析

  上面的错误信息就是因为编码冲突造成的。我们需要解码!

  解码的方法是decode('编码格式'),它可以将别的编码格式转换成unicode。例如decode('GBK')、decode('utf-8')。解码后爬取下来的网页就以unicode编码格式存储在内存里,然后可以被正常的进行正则分析,匹配,查找,而不会报错。

  同样我们也可以进行编码encode(),它可以将unicode编码格式转换成别的编码格式,一般都是utf-8。


  总结:其实编码问题没有想象中那么复杂,大家只要分清楚这里的两部分,就很容易搞定。可以利用上面的代码,注释掉

decode('GBK')这部分做个试验。有不正确的地方,请大家指正!