V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
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 · 2014-01-28 20:37:02 +08:00 · 10827 次点击
    这是一个创建于 3981 天前的主题,其中的信息可能已经有所发展或是发生改变。
    页面是这个:
    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 以后的东西吗?我还有什么没有做,应该怎么办呢?
    21 条回复    1970-01-01 08:00:00 +08:00
    RIcter
        1
    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
        2
    binux  
       2014-01-28 20:56:16 +08:00
    html.decode('gbk', 'replace')
    richiefans
        3
    richiefans  
       2014-01-28 20:59:21 +08:00   ❤️ 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  
       2014-01-28 21:06:55 +08:00
    @richiefans urllib2默认又不发gzip头。。
    LZ的代码也仅仅是编码问题
    RIcter
        5
    RIcter  
       2014-01-28 21:17:40 +08:00
    我在我电脑上正常跑啊..lz为何有错 orz
    2ex
        6
    2ex  
       2014-01-28 21:22:07 +08:00   ❤️ 1
    import sys
    reload(sys)
    sys.setdefaultencoding("UTF-8")
    stockss
        7
    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
        8
    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
        9
    destec  
       2014-01-28 23:19:13 +08:00
    漏了一句,原页面第5行定义了charset

    <meta http-equiv="Content-type" content="text/html; charset=gb2312" />
    picasso250
        10
    picasso250  
       2014-01-29 00:08:23 +08:00
    position 1-2: illegal multibyte sequence 打出十六进制,将不合法的逐一替换为空。或许只是几个字的编码有问题。
    larryzh
        11
    larryzh  
    OP
       2014-01-29 00:40:30 +08:00
    折腾了一下,应该是如 3 楼所说是 gzip 过的缘故。我使用
    larryzh
        12
    larryzh  
    OP
       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
        13
    msg7086  
       2014-01-29 02:21:07 +08:00
    @binux 因为有些网络环境会在不发gzip头的时候返回gzip内容。比如有些反代或者cdn在没搞好的情况下……
    binux
        14
    binux  
       2014-01-29 10:17:17 +08:00
    @msg7086 我估计新浪不会,因为我测试是ok的,估计是有透明代理
    Crossin
        15
    Crossin  
       2014-01-29 10:50:04 +08:00
    之前也踩过这个坑,抓sina默认拿到被gzip过的
    msg7086
        16
    msg7086  
       2014-01-29 11:28:15 +08:00
    @binux 透明代理 -> 反代

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

    解压之后decode依然可以会有问题,decode('gbk','ignore') 就好了 ,是部分编码解析不了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2947 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 00:39 · PVG 08:39 · LAX 16:39 · JFK 19:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.