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

2014 年 1 月 28 日
 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

输出:



编码问题参考了 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 以后的东西吗?我还有什么没有做,应该怎么办呢?
11611 次点击
所在节点    Python
21 条回复
RIcter
2014 年 1 月 28 日
一般我碰上这种问题,以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 年 1 月 28 日
html.decode('gbk', 'replace')
richiefans
2014 年 1 月 28 日
明显是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 年 1 月 28 日
@richiefans urllib2默认又不发gzip头。。
LZ的代码也仅仅是编码问题
RIcter
2014 年 1 月 28 日
我在我电脑上正常跑啊..lz为何有错 orz
2ex
2014 年 1 月 28 日
import sys
reload(sys)
sys.setdefaultencoding("UTF-8")
stockss
2014 年 1 月 28 日
# -*- 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 年 1 月 28 日
可以试试这个
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 年 1 月 28 日
漏了一句,原页面第5行定义了charset

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

折腾了一下,应该是如 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 年 1 月 29 日
@binux 因为有些网络环境会在不发gzip头的时候返回gzip内容。比如有些反代或者cdn在没搞好的情况下……
binux
2014 年 1 月 29 日
@msg7086 我估计新浪不会,因为我测试是ok的,估计是有透明代理
Crossin
2014 年 1 月 29 日
之前也踩过这个坑,抓sina默认拿到被gzip过的
msg7086
2014 年 1 月 29 日
@binux 透明代理 -> 反代

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

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

https://v2ex.xtra.eu.org/t/98597

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

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

© 2021 V2EX