Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 1022|回复: 0

【已解决】python中文字符乱码(GB2312,GBK,GB18030相关的问题)

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-7-12 15:39:38 | 显示全部楼层 |阅读模式
     

    http://againinput4.blog.163.com/blog/static/1727994912011111011432810/

     

    【已解决】python中文字符乱码(GB2312,GBK,GB18030相关的问题)

     

    【背景】

    在玩wordpress的一个博客搬家工具BlogMover,其包含几个python脚本,其中有个是163博客搬家用的163-blog-mover.py,实现抓取网易博客的日志,然后导出xml。

    但是其工具现在(2011-12-10)已经失效了。经过自己一点修改后,可以实现获得文章标题了。

    用法还是原先的用法:

     

     163-blog-mover.py -fhttp://againinput4.blog.163.com/blog/static/172799491201111893853485/

     

    获得的此篇日志的标题:

    【已解决】允许hi-baidu-mover_v2.py出错:UnboundLocalError: local variable 'linkNode' referenced before assignment

    中包含中文,在将该标题打印出来到log中后,却发现中文部分显示乱码:

    ????·??????????íhi-baidu-mover_v2.py???í??UnboundLocalError: local variable 'linkNode' referenced before assignment

    所以想要去除乱码,正确显示中文。

     

    【解决过程】

    1. 本身那段文字,是从网页中抓取的,关于该日志的中文编码,也已经从网页中的:

        <metahttp-equiv="content-type"content="text/html;charset=gbk"/>

    看出来是GBK了。
    而python中,原先默认编码发现是ascii,后来去通过:

    reload(sys)
    sys.setdefaultencoding('utf-8')

    去将默认编码设置为utf-8,但是结果输出还是乱码。

     

    2.后来网上找了一堆帖子, 包括最后这个:

    http://www.tangc.com.cn/view_article_117.html

    去尝试先对其解码,再编码:

    string.decode('GBK').encode(utf-8')

    结果还是乱码:

    隆戮虏驴路脰陆芒戮枚隆驴脭脢脨铆hi-baidu-mover_v2.py鲁枚麓铆拢潞UnboundLocalError: local variable 'linkNode' referenced before assignment

    而又去试了试其他的,比如:

    temp.string.strip().decode('GBK').encode('mcbs)

    输出也是乱码,和不转换之前是一样的。

    总之,还是无法及解决乱码问题。

     

    3.后来,在学习Beautiful Soup的时候:

    http://www.crummy.com/software/BeautifulSoup/documentation.zh.html#contents

     

     Beautiful Soup 会按顺序尝试不同的编码将你的文档转换为Unicode:
    • 可以通过fromEncoding参数传递编码类型给soup的构造器
    • 通过文档本身找到编码类型:例如XML的声明或者HTML文档http-equiv的META标签。 如果Beautiful Soup在文档中发现编码类型,它试着使用找到的类型转换文档。 但是,如果你明显的指定一个编码类型, 并且成功使用了编码:这时它会忽略任何它在文档中发现的编码类型。
    • 通过嗅探文件开头的一下数据,判断编码。如果编码类型可以被检测到, 它将是这些中的一个:UTF-*编码,EBCDIC或者ASCII。
    • 通过chardet库,嗅探编码,如果你安装了这个库。
    • UTF-8
    • Windows-1252

     

      得知Beautiful Soup默认已经可以通过你所给的链接中的HTML源码中的meta的http-equiv头,去解析charset,已经可以知道网页的编码是上面所显示的GBK了,而且自动会去以该编码获得网页内容,然后自动输出为utf-8的unicode了。

    所以python中去:

     

     print "###originalEncoding=",soup.originalEncoding,"declaredHTMLEncoding=",soup.declaredHTMLEncoding,"fromEncoding=",soup.fromEncoding
     就已经可以得到输出:

     

     

     ###originalEncoding= windows-1252 declaredHTMLEncoding= gbkfromEncoding= None
       了,但是也还是很奇怪,为何原先网页的编码,HTML中声明的是GBK,而Beautiful Soup解析出来的网页原始编码originalEncoding是windows-1252呢,两者不一样(我另外试了别的一个百度的网页,declaredHTMLEncoding是GBK,originalEncoding也是declaredHTMLEncoding)。

     

    也因此,自己手动尝试,在open URL的时候,给Beautiful Soup传递GBK参数,即:

     

     page = urllib2.build_opener().open(req).read()
    soup = BeautifulSoup(page, fromEncoding="GBK")
     结果也还是不行。

     

    关于此问题,后来网上找到了解释:
    Beautiful Soup gb2312乱码问题

    http://groups.google.com/group/python-cn/browse_thread/thread/cb418ce811563524

     

     请注意 gb2312 不是 “gb2312”,凡 gb2312 的请换成 gb18030. 

    微软将 gb2312 和 gbk 映射为 gb18030,方便了一些人,也迷惑了一些人。

     

       即,实际上该网页是GB18030的编码,所以按照这里:

    上午解决了网页解析乱码的问题

    http://blog.csdn.net/fanfan19881119/article/details/6789366

    (原始出处为:http://leeon.me/a/beautifulsoup-chinese-page-resolve

    的方法,传递GB18030给fromEncoding,才可以:

     

     page = urllib2.build_opener().open(req).read()
    soup = BeautifulSoup(page, fromEncoding="GB18030")
       而其中,也解释了,为何HTML标称的GBK的编码,但是却解析出来为windows-1252了:

     

     

     最近需要写一个python的RSS抓取解析程序,使用了feed parser。但是对于百度新闻的RSS,其编码方式为gb2312,feed parser探测出来的编码却是windows-1252,结果中文内容都是一堆乱码。

    问题在于,并不是feedparser不能识别出gb2312编码,而是国人们往往将gb2312与gbk编码等同,某些已经使用了gbk编码里的字符的,仍然声称内容为gb2312编码。feedparser对gb2312编码严格遵循gb2312字符集范围,当探测到超出这一范围的字符,便将编码回退到windows-1252。由于百度的RSS实际使用的应该是gbk编码,里面含有超出gb2312范围的字符,于是feedparser便擅自决定了将编码退回windows-1252,导致了中文乱码的现象。
       
    【总结】

     

    以后用python的Beautiful Soup去解析中文网页的话:

    1.如果本身网页的编码自己标称的,和本身其中文字符所用编码完全符合的话,即没有部分字符超出了其所标称的编码,比如标称为GBK,网页所有的内容,都的确是GBK编码,没有超出的其他字符(比如属于GB18030的编码),那么,是可以通过

     

      page = urllib2.urlopen(url)
    soup = BeautifulSoup(page) #此处不需要传递参数,BeautifulSoup也完全可以自己去解析网页内容所使用的编码
    print soup.originalEncoding

     

    而得到真实的网页的编码的

     

    2.讨论中文乱码问题之前,先解释关于中文字符编码:

    时间上的发展先后是,GB2312,GBK,GB18030,编码技术上都是兼容的。

    从所包含的中文字符个数来说,算是:GB2312 < GBK < GB18030,也因此,才可能会出现上面所说的,标称GB2312的,部分字符用到了GBK里面的,或者是标称GBK的,部分字符用到了GB18030里面的,所以被人家编码工具解析错误,退回认为编码是最基本的windows-2152了。

    而我这里的情况就是属于后者,网易博客网页中,自己声称是GBK,但是很多中文字符用的是GB18030。

    总的说,现在实际情况是,由于编写网页代码的人所用的字符编码所不同,以及自己在网页中声称的编码和实际自己网页所用的编码不同,导致了中文网页出现乱码。所以,要先搞懂这些中文字符编码之间关系,以及历史上的逻辑前后关系,才可能解决这类问题。

    关于中文字符编码,更多详细解释请参考这里:

    中文字符编码标准+Unicode+Code Page

    http://bbs.chinaunix.net/thread-3610023-1-1.html

     

    所以:

    (1)如果是网页标称为GB2312,但是部分字符用到了GBK的了那么解决办法就是在调用BeautifulSoup,传递参数fromEncoding="GBK",即:

     

     page = urllib2.build_opener().open(req).read()
    soup = BeautifulSoup(page, fromEncoding="GBK")

     

    (2)如果是网页标称为GBK,但是部分字符用到了GB18030的了,那么解决办法就是在调用BeautifulSoup,传递参数fromEncoding="GB18030",即:

     

    page = urllib2.build_opener().open(req).read()
    soup = BeautifulSoup(page, fromEncoding="GB18030")

     

    (3)实际上由于GB18030从字符数上都涵盖了GB2312和GBK,所以如果是上述两种任意情况,即只要是中文字符出现乱码,不管是标称GB2312中用到了GBK,还是标称GBK中用到了GB18030,那么都直接传递GB18030,也是可以的,即:

     

     soup = BeautifulSoup(page, fromEncoding="GB18030")
      即可。
     

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-12-22 16:31 , Processed in 0.059628 second(s), 30 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表