Python利用urllib2抓取网页返回乱码的问题代码:输出:直接print中文是可以的,注释的中文也不会乱码,就解析网页乱码求有用解决方案!!【问题解答】从问题现象到问题本质,一点点帮你分析为何如何,以及如何解决问题1.首先,根据之前的Python的IDE的经验:【整理】各种Python的IDE(集成开发环境)的总结和对比从上述截图,基本上,可以推测出来,其用的是:【记录】使用Python的IDE:Eclipse+PyDev2.所以,为了完全重现其问题,专门去PyDev中建立了对应的项目。代码为:?12345678910111213141516#-*-coding:utf-8-*-'''CreatedonOct18,2013@author:CLi'''fromurllibimporturlopendefgetHtml(url):page=urlopen(url)html=page.read()page.close()returnhtmlif__name__==__main__:url==getHtml(url)printhtml然后,输出,果然和其一样:3.对于此现象的原因:(根据:详解抓取网站,模拟登陆,抓取动态网页的原理和实现(Python,C#等)的:【整理】关于HTML网页源码的字符编码(charset)格式(GB2312,GBK,UTF-8,ISO8859-1等)的解释)先去确认了所要处理的网页:中有:?1metahttp-equiv=Content-typecontent=text/html;charset=gb2312/(再根据:字符编码简明教程)可知,此处的代码处理中,如果需要解码为Unicode,最好用GBK。而此处得到的sina网页的字符串,是GB2312对应的,在Eclipse+PyDev中的console中输出,结果却乱码了。则可以确定:Eclipse+PyDev的console中,所用字符编码不是GB2312(也不是GBK或GB18030)猜测:估计是用的,相对常见的,UTF-84.但是不管其用什么编码,将Unicode的字符串输出,则肯定应该是可以的:5.为了验证上面的PyDev的console是UTF-8的猜测,所以去用代码:?1234567891011121314151617181920212223#-*-coding:utf-8-*-'''CreatedonOct18,2013@author:CLi'''fromurllibimporturlopendefgetHtml(url):page=urlopen(url)html=page.read()page.close()#uniCodehtml=html.decode(GBK)#returnuniCodehtmluniCodehtml=html.decode(GBK)utf8html=uniCodehtml.encode(UTF-8)returnutf8htmlif__name__==__main__:url==getHtml(url)printhtml结果输出果然是所预测的,正常的:6.接下来,就很明显了:需要搞清楚,为何此处:Eclipse+PyDev的Console中,(不是我们之前所以为的,调用了Windows的cmd,以为是GBK编码)却是UTF-8编码然后参考:PrintingUnicodeineclipsePydevconsoleandinIdle而去看看:结果在Eclipse的Window-Preferences中,找了半天,都没有找到关于console的encoding方面的设置。最后是在:选择你的PyDev项目-Run-RunConfiguration-PythonRun-选择你当前的PyDev项目-Common-Encoding才看到:当前的,你的PyDev项目,运行期间,所用的console的编码是utf-87.对应的,去改为GBK:然后再点击Run,结果,用之前,将Unicode故意转为UTF-8的话,则输出此时就是,所预料到的,乱码了:对应的,再去用,最原始的代码,直接输出(得到的GB2312的sina网页),不做任何转换的代码:8.由此,可以完全明白原因了:(1)从sina获得的html网页,这个字符串,本身的字符编码为:GB2312(2)直接print输出到,Eclipse+PyDev,中的console时,由于console默认是UTF-8编码,所以:将GB2312的sina的html网页字符串输出到UTF-8的Eclipse+PyDev的console中必然导致乱码。而由于前面多次的尝试可知,解决办法有多种:(1)代码不改:?123fromurllibimporturlopendefgetHtml(url):456789101112page=urlopen(url)html=page.read()page.close()returnhtmlif__name__==__main__:url==getHtml(url)printhtml但是去改,Eclipse+PyDev的console的字符编码,从UTF-8改为GBK(或GB2312,或GB18030):选择你的PyDev项目-Run-RunConfiguration-PythonRun-选择你当前的PyDev项目-Common-Encoding-改为GBK(2)不改Eclipse+PyDev的console的字符编码,仍保持旧的UTF-8的配置,但是去改代码:?1234567891011121314fromurllibimporturlopendefgetHtml(url):page=urlopen(url)html=page.read()page.close()uniCodehtml=html.decode(GBK)returnuniCodehtmlif__name__==__main__:url==getHtml(url)printhtml即,获得GB2312的html后,去decode为Unicode,然后直接输出Unicode字符串到UTF-8的Eclipse+PyDev的console中,则比如也是可以正常显示无乱码的(内部会自动将输出的Unicode转换为当前console的UTF-8编码的字符串的)(3)基于上面那种方式,(不改Eclipse+PyDev的console的字符编码,仍保持旧的UTF-8的配置),但是在转换为Unicode后,再故意转为输出目标(此处的Eclipse+PyDev的console)的编码,即UTF-8:?1234567891011121314151617fromurllibimporturlopendefgetHtml(url):page=urlopen(url)html=page.read()page.close()#uniCodehtml=html.decode(GBK)#returnuniCodehtmluniCodehtml=html.decode(GBK)utf8html=uniCodehtml.encode(UTF-8)returnutf8htmlif__name__==__main__:url==getHtml(url)printhtml也是可以保证输出的网页是正常的,中文不是乱码。关于返回的网页是否要解压缩另外,有人提到的:(以为此处获得的网页是压缩的)所以需要对于抓取回来的网页进行解压缩此处实际结果证明了:是不需要的。其背后的原理和逻辑是:(正常情况下)只有当你抓取网页所提交的请求,包含了说你支持(即需要)返回压缩的网页(人家服务器)才返回对应的压缩的网页详见:【总结】静态网页抓取,动态网页抓取,模拟登陆的注意事项和心得中的:“返回的html内容是二进制的乱码”进一步分析问题的现象和背后的本质至此,上面的所有分析,还只是:和解压代码无关,和字符串编码有关但是:此处,才注意到,提问者提问所截的图看起来,还的确是:打印出来的乱码像是二进制级别的字符串乱码而非之前所讨论的,中文的乱码此刻,猜测问题最大的可能性是:提问者,没有给出背后相关的其所用的所有的代码估计其代码,除了此处截图给出的代码之外还是在别处,用到了对应的:【总结】静态网页抓取,动态网页抓取,模拟登陆的注意事项和心得中的:“返回的html内容是二进制的乱码”所提到的:添加了对应的头信息,其中包含了:Accept-Encoding设置了gzip,deflate从而导致:此处,返回的网页,直接打印出现二进制那种的乱码(而不是字符编码设置错误的,只会导致中文异常的那种乱码)所以:要么是我上述推测错了;要么是,我推测是对的,而提问者,没有给出错误现象背后的,相关的所有的代码和背景条件o-导致上面耗费半天时间分析编码错误导致中文乱码,对于此问题来说,算是白费功夫了-当然对于其他人不熟悉的此方面内容的,肯定还是有参考意义的无论哪种情况,此种,二进制乱码的解决办法是:核心相关代码:?1234567891011121314151617181920212223#print---beforeunzip,len(respHtml)=,len(respHtml);respInfo=resp.info();#Server:nginx/1.0.8#Date:Sun,08Apr201212:30:35GMT#Content-Type:text/html#Transfer-Encoding:chunked#Connection:close#Vary:Accept-Encoding#...#Content-Encoding:gzip#sometime,therequestusegzip,deflate,butactuallyreturnedisun-gziphtml#-responseinfonotincludeaboveContent-Encoding:gzip#eg::deflateif(Content-EncodinginrespInfo):if(gzip==respInfo['Content-Encoding']):respHtml=zlib.decompress(respHtml,16+zlib.MAX_WBITS);elif(deflate==respInfo['Content-Encoding']):respHtml=zlib.decompress(respHtml,-zlib.MAX_WBITS);更详细的解释,参见:【总结】静态网页抓取,动态网页抓取,模拟登陆的注意事项和心得中的:“返回的html内容是二进制的乱码”对应的,很明显,上面的核心代码,本来就无需,无法,直接加入到,此处提问者所贴出的那段代码的:因为:其所给出的代码,根本就不应该存在此问题才对。更加,功能丰富的,用于抓取网页的函数,其实我早就帮你们封装好了,只是你们不知道,没去用而已。感兴趣的,自己去看:获得Url地址的响应:getUrlResponse和:获得Url返回的HTML网页(源码)内容:getUrlRespHtml即可。【总结】对于:Eclipse+PyDev的console,默认是UTF-8,而不是GBK导致让不熟悉的人误以为,输出GBK(或Unicode)的字符串,会像输出到G