[求助]用 urllib2 抓取到的一个页面出现了惨不忍睹的编码,我该怎么做?

2014-01-28 20:37:02 +08:00
 larryzh
页面是这个:
http://sports.sina.com.cn/g/premierleague/index.shtml

代码:
# coding: u8
import urllib2
url = "http://sports.sina.com.cn/g/premierleague/index.shtml"
response = urllib2.urlopen(url)
html = response.read()
print html

输出:
��wױ8�3�����'͠�L/�J
���.u�Vխ�[w�5��;:�S��煝{7l��!�Z����p8�'-��y϶���=e�P�Usł��;��__�Zj
�::������]�K��챵��
e�Y�ڕkV���%I���B��U�VY�"���*')��ڤ��S.�
��JT�>"T�T�Zk+�!x��*)l�d2I�����,��kUU�ҭ�/k�����X�j�jk�HI� ��U���0�n2}j��US�ݲ"�>!�p��j^[����LJg�'o^=�����Nq���ȕ7n|�57yy����'��\��ul
j���=�9T,g/��t�0�ݕ7�'^�������o�|v}>8=7�흯!��tp�����ٹˏgF�S��?�z��d���~�`�����M��u�C%�U2�\ �f���߉V��q�ߍ7�~2~��ɓ���lE������=}���M��}���X��w�o}u��s�'>?�*��zp����S�:���7Oݚ�~��ч�b����=��
HK!��s�عi�nQ����R��}@�TsY�|,�#b\d�+�#yM@qaR��TP�V�N�������w
��?[�((t�G���P��,�����A��$�O���/�E�XP�)���oN�gA����\�`�Z�������
��4
e�L7ȓVn+
Ʉ�e�R fT��`&WՂ�bV
f{
�j_p@-�@�[I�b�_ͷ��CZ����'!4�O1C�,�کhy b0W(ժ�Z��˨�V5��-���ټ�X)��5���{Ek����v��XÝN �(P�PU���Ck��ϫ��? ��j(�
�V3{��Z!��LOO�P+��L��P%WP���L!\=�! ���@X�D8ׯ�j�p�T,W+�#we~م ��{C�Bo@�_Y+ij��p;�^,�=�(��h� :�NxH�����|A�����r��]-���|��Bk�q<
ڻ�+}��.ܹl�t.�)�c�pt�RX���J4CJЃB��v@����B�X��d�P&�����6��dó��gs�R^=�/f���b�@�����s�#m} uZ���h�.V�80_)��$.1W�
h��S��*z�Q��J��Ñ��|��ă{�n�I�P����a±a#ن��L<���SA
%���^y�g2���*�\�f�xJ���h�Q�h_�F��BK���(c��%c��BKw���aH��eRB� ��8�w�6��<�Ͼ���K�� ���@.��k�*[����k�|^�_�¹BV;��,���p�u�]2�4��Y�
�B��wԢ���C�m�3`��>5���#FzF�G-%�Ũ
W��������0A�{�TȪ�#���u�4��@e��24�߈���*�:*�6Ђt&��XGe�@dc�%�cເ�h�|΀�y�����$Hh��Gv�3�s$(Y)�sY�M��v�E@l�C(��.�tk��ب�6�K��(�E;�Op1?:
D�����6�wОƘfO&�����zq�Z3Z>�����0�M�C��{�ڟ�i#.��
tPڻu�-�u�-�t3�8�X W���t2h�!�.>9;TVK��r�j_��$�yAB�Z�Ȋ�6���.ƭ��I��\y�K:¬
s��#lh��sx�zb=I��Nse�/��FUad�4�H3�l�n�Ho0T�^"j�*�]y�fr�MY!���׋��-#I�(�YVaΡ@���1kE뗴����2=qRt�ۈ��h@y�@�(GX)�I-Z�$l�NX�,����vg��^~�cE��
/虬&j�z����=АUd��Y��_���_�\FG����A}

编码问题参考了 http://in355hz.iteye.com/blog/1860787 ,感觉基本明白怎么回事儿了,按理说

isinstance(html, str) == True

并且页面的编码确定为 GBK,那么

html.decode('gbk').encode('utf-8')

就应该解决问题的,可是收到这样的提示:

UnicodeDecodeError: 'gbk' codec can't decode bytes in position 1-2: illegal multibyte sequence

我也试过其它的网站,就新浪会抓到这些鬼东西,这些是 gzip 以后的东西吗?我还有什么没有做,应该怎么办呢?
10824 次点击
所在节点    Python
21 条回复
RIcter
2014-01-28 20:54:36 +08:00
一般我碰上这种问题,以xxx为例..
首先,#coding=utf-8在第一行不可少
当然随你喜欢可以换成#coding: utf-8 或者#coding: -*- utf-8 -*-
然后xxx = xx

开始尝试如下:

print str(xxx)
print str(xxx).decode('utf-8')
print str(xxx).encode('utf-8')
print str(xxx).decode('gbk')
print str(xxx).encode('gbk')
print xxx.decode('utf-8')
print xxx.encode('utf-8')
print xxx.decode('gbk')
print xxx.encode('gbk')

以上。
如果还不能解决,你看看页面编码是啥..
还不行..反正我是行..
binux
2014-01-28 20:56:16 +08:00
html.decode('gbk', 'replace')
richiefans
2014-01-28 20:59:21 +08:00
明显是gzip过的吧

def fetchHtml(url):
#url="http://www.baidu.com/s?wd="+urllib2.quote(keyword)
try:
request = urllib2.Request(url)
request.add_header('Accept-encoding', 'gzip')
opener = urllib2.build_opener()
f = opener.open(request)
isGzip = f.headers.get('Content-Encoding')
#print isGzip
if isGzip :
compresseddata = f.read()
compressedstream = StringIO.StringIO(compresseddata)
gzipper = gzip.GzipFile(fileobj=compressedstream)
data = gzipper.read()
else:
data = f.read()
return data
except exceptions,e:
print e
#returnhtml=urllib2.urlopen(url).read()
return fetchHtml(url)
binux
2014-01-28 21:06:55 +08:00
@richiefans urllib2默认又不发gzip头。。
LZ的代码也仅仅是编码问题
RIcter
2014-01-28 21:17:40 +08:00
我在我电脑上正常跑啊..lz为何有错 orz
2ex
2014-01-28 21:22:07 +08:00
import sys
reload(sys)
sys.setdefaultencoding("UTF-8")
stockss
2014-01-28 22:49:02 +08:00
# -*- coding: UTF-8 -*-

import urllib2
url = "http://sports.sina.com.cn/g/premierleague/index.shtml"
response = urllib2.urlopen(url)
html = response.read()
print html
destec
2014-01-28 23:17:50 +08:00
可以试试这个
import urllib2

url = "http://sports.sina.com.cn/g/premierleague/index.shtml"
response = urllib2.urlopen(url)
html = response.read()
print html.decode('gb2312', 'ignore').encode('utf-8')

我把楼上的方法都试了,都是乱码。。
destec
2014-01-28 23:19:13 +08:00
漏了一句,原页面第5行定义了charset

<meta http-equiv="Content-type" content="text/html; charset=gb2312" />
picasso250
2014-01-29 00:08:23 +08:00
position 1-2: illegal multibyte sequence 打出十六进制,将不合法的逐一替换为空。或许只是几个字的编码有问题。
larryzh
2014-01-29 00:40:30 +08:00
折腾了一下,应该是如 3 楼所说是 gzip 过的缘故。我使用
larryzh
2014-01-29 00:52:15 +08:00
囧了,上面那个回复按错发出去了,删不掉,这里继续

折腾了一下,应该是如 3 楼所说是 gzip 过的缘故。我使用:
html = gzip.GzipFile(fileobj=StringIO.StringIO(html), mode="r")
html = html.read().decode('gbk').encode('utf-8')
终于输出可读的内容了,编码也正确了。

于是,对于 gzip 解码又有了个疑问,就是为什么不能直接用 zlib.decompress() 来直接解压缩字符串,而非要通过 gzip 和 StringIO 麻烦兮兮地绕道呢?如果我使用:
html = zlib.decompress(html)
会输出错误:
zlib.error: Error -3 while decompressing data: incorrect header check

Google一下发现了:
http://stackoverflow.com/questions/1838699/how-can-i-decompress-a-gzip-stream-with-zlib
有同学遇到类似的问题,也可以参考这里。

主贴中的问题算是解决了,非常感谢所有楼上的同学!
msg7086
2014-01-29 02:21:07 +08:00
@binux 因为有些网络环境会在不发gzip头的时候返回gzip内容。比如有些反代或者cdn在没搞好的情况下……
binux
2014-01-29 10:17:17 +08:00
@msg7086 我估计新浪不会,因为我测试是ok的,估计是有透明代理
Crossin
2014-01-29 10:50:04 +08:00
之前也踩过这个坑,抓sina默认拿到被gzip过的
msg7086
2014-01-29 11:28:15 +08:00
@binux 透明代理 -> 反代

@Crossin 握手。我也是之前被一些坑爹反代坑过……
binux
2014-01-29 11:39:03 +08:00
@msg7086 我指的是用户侧的代理,比如小ISP搞的
cloverstd
2014-01-29 13:02:16 +08:00
gzip
我之前抓新浪,有时返回的是gzip压缩过的,有时没有gzip压缩
我是这样判断的
flag = 'Content-Encoding' in headers and headers['Content-Encoding'] == "gzip"
mengzhuo
2014-01-29 16:32:17 +08:00
自侦测编码的库——>chardet
你值得拥有
crazycookie
2014-01-31 23:45:10 +08:00
请使用 requests 库

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/98597

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX