python中文字符乱码(GB2312,GBK,GB18030相关的问题)

转自博主 crifan http://againinput4.blog.163.com/blog/static/1727994912011111011432810/

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

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

用法还是原先的用法:

 163-blog-mover.py -f http://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. 本身那段文字,是从网页中抓取的,关于该日志的中文编码,也已经从网页中的:

<meta http-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= gbk fromEncoding= 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")

即可。

时间: 2024-11-19 12:14:45

python中文字符乱码(GB2312,GBK,GB18030相关的问题)的相关文章

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

http://againinput4.blog.163.com/blog/static/1727994912011111011432810/ [背景] 在玩wordpress的一个博客搬家工具BlogMover,其包含几个python脚本,其中有个是163博客搬家用的163-blog-mover.py,实现抓取网易博客的日志,然后导出xml. 但是其工具现在(2011-12-10)已经失效了.经过自己一点修改后,可以实现获得文章标题了. 用法还是原先的用法:  163-blog-mover.py

GB2312,GBK,GB18030,UTF8四种汉字编码标准有什么区别和联系

 从GB2312.GBK 到 GB18030,这些编码方法是向下兼容的,即同一个字符在这些方案中总是有相同的编码,后面的标准支持更多的字符.在这些编码中,英文和中文可以统一地处理.区分中文编码的方法是高字节的最高位不为 0.按照程序员的称呼,GB2312.GBK 到 GB18030 都属于双字节字符集 (DBCS). 以下是这四种字符集的包含关系:GB2312 < GBK < GB18030 < UTF8 ---------------------------------------

ubuntu下解压zip rar中文字符乱码的问题

如题,解压zip rar中文乱码的问i题一直困扰着我,每次都要到window系统下解压,很是不方便,今天终于把这类问题解决了.整理总结分享如下 一 .    解决 Rar 压缩文件乱码问题 Rar 压缩在 Ubuntu 下可能出现乱码,这是由于安装了 rar 软件包(开源 Rar 压缩格式解压工具), 解决方法是安装闭源的 unrar 软件包,在终端依次输入以下命令即可: sudo apt-get remove rar sudo apt-get install p7zip-full p7zip-

jsp与mysql中的中文字符乱码问题

刚开始自学jsp,在练习的过程中遇到了一个很严重的问题,就是中文字符乱码的问题,我用了三天的时间,搜集资料,终于解决了这个问题,现在对学到的东西进行一下总结整理. 1.首先是jsp页面显示乱码的问题,<title></title>标签中有中文有英文,设置<meta charset="utf-8" > 显示乱码,改为gbk则可正常显示,其他页面使用utf-8则显示正常.最终发现是因为文件创建是用了不同的方法,一般情况下,用记事本编写代码,文件另存为*.

笔记:PHP查询mysql数据后中文字符乱码

新建表Clubs CREATE TABLE `Clubs` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(30) CHARACTER SET utf8 NOT NULL DEFAULT '', PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; id name 1 程序员2 架构师3 产品经

mysql中采用concat来拼接中文字符乱码解决方式(转)

mysql中采用concat来拼接中文字符乱码解决方式 - fuxuejun的专栏 - 博客频道 - CSDN.NET http://blog.csdn.net/fuxuejun/article/details/6284725 mysql concat乱码问题解决 concat(str1,str2) 当concat结果集出现乱码时,大都是由于连接的字段类型不同导致,如concat中的字段参数一个是varchar类型,一个是int类型或doule类型,就会出现乱码. 解决方法:利用mysql的字符

Keil uVision4 代码编辑器中文字符乱码问题

MDK-ARM 使用中一直有个很纠结的问题,中文字符支持不好. 比如写代码注释,使用中文删除字符就会只删除一半问题.复制粘贴代码中间有中文就会出现乱码问题. 想过换IAR,新学个IDE也麻烦,上面的问题也不很大稍微绕一下也能解决,所以一直没换. 发现其实这个根本不是问题,安装好后默认是ANSI编码,所以会出现上述问题.只要把编码改成UTF-8编码就能解决上述烦恼. 设置步骤:     1.选择菜单:[Edit]->[Configuration]       2.页签[Editor]中 Gener

SpringMVC项目中中文字符乱码问题及解决办法总结(非专业最优解决办法) -- ajax传值乱码; request.getParameter()乱码;

情况一: ajax中传值时是乱码(后台可以获取到中文字符,但用@ResponseBody返回时前台为乱码) 情况二: Controller 中 request.getParameter()获取到的是乱码 @RequestMapping(params = "method=submit") public String submit(HttpServletRequest request, ModelMap modelMap) throws Exception{ String uname =

web工程中文字符乱码:try { res.setContentType(&quot;text/html;charset=gbk&quot;); PrintWriter pw=res.getWriter(); ;;; }

输入正确的name ,pwd  跳转到main 页面 证明:登录信息确认基本正确 用户名,密码不对时提示:信息错误 注意编码格式: 应设置如下:在try中设置字符编码为gbk,在try外有时出错,设置res字符编码格式,然后再getWriter,才是正确流程. (PS:网上的修改tomcat server.xml的方法尝试过,这里不适用) 原因如下 确实是这个原因: 可以正确输出. 而 会显示乱码.