Python解码

2016.3.3部分

上手爬虫第一天,就遇到了一个麻烦的问题:解码解不出来。
先上源码:

import urllib
import urllib.request

data = {}
data['word'] = 'LEGO'

url_values = urllib.parse.urlencode(data)
url = 'http://www.baidu.com/s?'
full_url = url + url_values

response = urllib.request.urlopen(url)
data = response.read()
data = data.decode('utf8')
print (data)

这段代码就等于是在百度搜索“LEGO”,然后读取搜索到的网页结果。跑一下,发现提示UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbe in position 60: invalid start byte。上网查了下资料,发现有几三个地方没太搞懂,搞懂了就能解决这个解码问题了:

  1. response.read()返回的到底是什么编码字符?是html的代码对吧,那么这个html代码是用什么方法来编码的呢?
  2. decode('?')中需要用什么编码方式才能正确解码?如果知道问题1的答案,那么这个问题2也容易解决了。由于不知道是什么编码方式,那么将?一个个使用uft8big5unicodegbk等编码方式尝试,结果都是类似的提示,只是报错的行数不同。
  3. 我在网上尝试了一下解码后再次编码的方法,变成了data = data.decode('utf8').encode('gbk'),看能不能有突破,发现不行后,删掉了后加上的代码,只保留data = data.decode('utf8'),结果运行.py后还一直提示UnicodeEncodeError: 'gbk' codec can't encode character '\xbb' in position 25145: illegal multibyte sequence,最后只能是将整行注释掉才恢复正常(输出html源码),但去掉注释后又弹出encode提示,代码中明明没有了encode啊!我的内心几乎是崩溃的!

在继续查资料后,决定先放下这个解码问题,先做好数据存储那一块,再回头慢慢解决切割和解码问题,没准到时候就懂了。


2016.3.10部分

在使用了Requests和BeautifulSoup第三方库后,打算将爬到的数据打印出来看一下:

import requests
import urllib.parse
from bs4 import BeautifulSoup

response = requests.get('http://www.baidu.com')
soup = BeautifulSoup(response.text, "html.parser")

print (soup.title.text)
print (soup.body.text)

结果,还是报了跟之前一样的编码错误:UnicodeEncodeError: 'gbk' codec can't encode character '\xa0' in position 12734: illegal multibyte sequence,于是继续查,终于找到原因了。
解决方法如下:

  1. 忽略cmd的显示问题,直接存为文件输出

其实呢,这是windows控制台本身的显示编码, 在dos窗口标题,右键菜单选择属性,可以看到控制台的默认编码为GBK(cp936)。
所以说,问题不在python,不在网页,而是那个呆板的dos控制台。
解决方法呢,简单点可以写到本地文件中查看,复杂点的就留给你去折腾了。 注意,这只是dos控制台的显示问题,对于其中字符串的处理完全不受阻碍。 看不看得见,它就在内存里,该干嘛还干嘛。

  1. 使用函数将爬取的数据保存为文件

def save_file(data, path):
files = open(path, 'wb')
files.write(data)
files.close()
save_file(soup.title.text, 'p7_title.txt')
save_file(soup.body.text, 'p7_body.txt')

  1. 结果报了另外一个错:TypeError: a bytes-like object is required, not 'str',那么再对爬到的数据使用strip再encode的方法

save_file(soup.title.text.strip('\00').encode(), 'p7_title.txt')
save_file(soup.body.text.strip('\00').encode(), 'p7_body.txt')

  1. 如此一来,虽然是绕弯解决的,没有直面问题,但还是顺利解决了问题,并且已经拿到了需要的数据。

相关资料

  • 关于Python打印网页内容时报错

你可能感兴趣的:(Python解码)