推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
larryzh
V2EX  ›  Python

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

  •  1
     
  •   larryzh ·
    larryisthere · Jan 28, 2014 · 11562 views
    This topic created in 4493 days ago, the information mentioned may be changed or developed.
    页面是这个:
    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 以后的东西吗?我还有什么没有做,应该怎么办呢?
    21 replies    1970-01-01 08:00:00 +08:00
    RIcter
        1
    RIcter  
       Jan 28, 2014
    一般我碰上这种问题,以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
        2
    binux  
       Jan 28, 2014
    html.decode('gbk', 'replace')
    richiefans
        3
    richiefans  
       Jan 28, 2014   ❤️ 2
    明显是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
        4
    binux  
       Jan 28, 2014
    @richiefans urllib2默认又不发gzip头。。
    LZ的代码也仅仅是编码问题
    RIcter
        5
    RIcter  
       Jan 28, 2014
    我在我电脑上正常跑啊..lz为何有错 orz
    2ex
        6
    2ex  
       Jan 28, 2014   ❤️ 1
    import sys
    reload(sys)
    sys.setdefaultencoding("UTF-8")
    stockss
        7
    stockss  
       Jan 28, 2014
    # -*- 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
        8
    destec  
       Jan 28, 2014
    可以试试这个
    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
        9
    destec  
       Jan 28, 2014
    漏了一句,原页面第5行定义了charset

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

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

    @Crossin 握手。我也是之前被一些坑爹反代坑过……
    binux
        17
    binux  
       Jan 29, 2014
    @msg7086 我指的是用户侧的代理,比如小ISP搞的
    cloverstd
        18
    cloverstd  
       Jan 29, 2014
    gzip
    我之前抓新浪,有时返回的是gzip压缩过的,有时没有gzip压缩
    我是这样判断的
    flag = 'Content-Encoding' in headers and headers['Content-Encoding'] == "gzip"
    mengzhuo
        19
    mengzhuo  
       Jan 29, 2014
    自侦测编码的库——>chardet
    你值得拥有
    crazycookie
        20
    crazycookie  
       Jan 31, 2014
    请使用 requests 库
    dingyaguang117
        21
    dingyaguang117  
       Feb 6, 2014
    目测应该是 gzip 或者其他方式压缩,按理说你没有上传 accept-encoding 服务器不应该给你压缩的,不过有的就是这么不遵循规则。

    解压之后decode依然可以会有问题,decode('gbk','ignore') 就好了 ,是部分编码解析不了
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   4895 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 111ms · UTC 09:39 · PVG 17:39 · LAX 02:39 · JFK 05:39
    ♥ Do have faith in what you're doing.