【python】抓取网页gb2312/gbk编码乱码

做了个网络爬虫抓取网页,但如果网页是gbk/gb2312编码,则会出现乱码问题,如下:
取得文字后,直接打印,输出结果str如下:

¹óÖÝÈËÊ¿¼ÊÔÐÅÏ¢Íø_¹óÖÝÈËÊ¿¼ÊÔÍø_¹óÖݹ«ÎñÔ±¿¼ÊÔÍø_¹óÖÝÖй«

这个问题困扰我好长时间,baidu,google了一番也没有找到完全可行的方法,继续瞎折腾,最后居然搞出来了!编码转换来转换去的,还是得不到解决。特意把问题总结下来,分享给大家,互相学习!(有时问题不复杂很容易解决,如果没有找到问题的突破口的话,那么通向解决问题的路程就很遥远了)总之,遇到问题时,多选择几种方法试试,总有一种方法可以解决的。

1.改变网页源代码的编码格式(重点)

# -*- coding:utf8 -*-

import urllib2

req = urllib2.Request("http://www.baidu.com/")
res = urllib2.urlopen(req)
html = res.read()
res.close()
html = unicode(html, "gb2312").encode("utf8")  #gb2312--->utf-8
print html

2.python抓取网页时字符集转换问题处理方案

有时候我们采集网页,处理完毕后将字符串保存到文件或者写入数据库,这时候需要制定字符串的编码,如果采集网页的编码是gb2312,而我们的数据库是utf-8的,这样不做任何处理直接插入数据库可能会乱码(没测试过,不知道数据库会不会自动转码),我们需要手动将gb2312转换成utf-8。
首先我们知道,python里的字符默认是ascii码,英文当然没问题啦,碰到中文的时候立马给跪。
不知道你还记不记得,python里打印中文汉字的时候需要在字符串前面加 u:
print u”来搞基吗?”
这样子中文才能显示,这里面的u的作用就是将后面的字符串转换为unicode码,这样中文才能得到正确的显示。
这里与之相关的有一个unicode()函数,用法如下

str="来搞基"
str=unicode(str,"utf-8")
print str

与u的区别是,这里用unicode将str转换为unicode编码,需要正确指定第二个参数,这里的utf-8是我test.py脚本自身的文件字符集,默认的可能是ansi。
unicode这是一个关键,下面继续
我们开始抓取百度首页,注意,游客访问百度首页,查看网页源代码,它的charset=gb2312。

import urllib2

def main():
  f=urllib2.urlopen("http://www.baidu.com")
  str=f.read()
  str=unicode(str,"gb2312")
  fp=open("baidu.html","w")
  fp.write(str.encode("utf-8"))
  fp.close()

if name == 'main' :
  main()

解释:

我们首先用urllib2.urlopen()方法将百度首页抓取到,f是句柄 ,用str=f.read()将所有源代码读入str中
搞清楚,str里面就是我们抓取的html源代码,由于网页默认的字符集是gb2312,所以如果我们直接保存到文件中,文件编码将是ansi。
对于大部分人来说,其实这就足够了,但是有时候我就想把gb2312转换成utf-8的该怎么办呢?
首先:
str=unicode(str,"gb2312")#这里的gb2312就是str的实际字符集,我们现在将其转换成unicode
然后:
str=str.encode("utf-8")#将unicode的字符串重新编码成utf-8
最后:
将str写入到文件中,打开文件看一下编码属性,发现是utf-8的了,把

总结:

我们回顾一下,如果需要将字符串按照指定的字符集保存,有以下几个步骤:
1:用unicode(str,”原来的编码”)将str解码成unicode字符串
2:将unicode字符串str 使用 str.encode(“指定的字符集”) 转换成你指定的字符集
3:将str保存文件,或者写入数据库等操作,当然,编码你已经指定了,不是吗?

3.用lxml解析html

用lxml.etree做网络爬虫抓取网页,但如果网页是gbk/gb2312编码,则会出现乱码问题,如下:
取得文字后,直接打印,输出结果v如下:
¹óÖÝÈËÊ¿¼ÊÔÐÅÏ¢Íø¹óÖÝÈËÊ¿¼ÊÔÍø¹óÖݹ«ÎñÔ±¿¼ÊÔÍø_¹óÖÝÖй

这个v的类型又是

response.encoding = 'utf-8'
page = etree.HTML(response.content)
nodes_title = page.xpath("//title//text()")

这样打印出来的nodes_title[0]就为正常的中文显示了。

特别注意的是,response.text很容易出现编码问题的,以后用response.content。

扫描二维码关注公众号,回复: 2888244 查看本文章

猜你喜欢

转载自blog.csdn.net/qq_38486203/article/details/81357525