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
soratadori
V2EX  ›  Python

读取编码 utf-8 网页出现问题 [Non-BMP character not supported in Tk]

  •  
  •   soratadori · 2015-04-01 03:07:19 +08:00 · 5136 次点击
    这是一个创建于 3525 天前的主题,其中的信息可能已经有所发展或是发生改变。
    环境:python版本3.4,IDE是自带的那个

    一般来说编码问题的话,多试几个办法总能解决,但是这个怎么也读不出来。该网页响应头返回的是 charset=UTF-8

    code:
    page = resp.read().decode('utf-8' )
    print(page)

    这样写的话用utf-8解不出来,换成其他的也解不出来。
    如果在后面加上一句ignore的话,其他编码方式能解的出来了,但是出现乱码,而utf-8仍然解不出来,并且错误由第一行转移到了第二行,出现错误代码 [UnicodeEncodeError: 'UCS-2' codec can't encode characters in position 2528-2528: Non-BMP character not supported in Tk] ,由此可以推断使用utf-8是没错的。但是这个错误代码的解决方法找了半天也没找到。

    有人知道怎么解决吗
    5 条回复    2015-04-03 00:56:04 +08:00
    aaaa007cn
        1
    aaaa007cn  
       2015-04-01 08:08:47 +08:00
    错误提示已经讲得很清楚了
    Non-BMP character not supported in Tk
    Tk 不支持 Non-BMP(非基本多文种平面)字符
    而 IDLE 正是基于 Tcl/Tk 的

    关于 Non-BMP 可以参考 wikipedia
    https://en.wikipedia.org/wiki/Plane_%28Unicode%29

    另外
    问题是出在 print(page),而不是之前的 decode
    显式 encode 吧
    print(page.encode('utf-8'))
    soratadori
        2
    soratadori  
    OP
       2015-04-01 21:05:39 +08:00
    @aaaa007cn 后面再加上 .encode('utf-8')) 我也试过,但是出来的结果是:

    b'\x1f\x08\x00\x00\x00\x00\x00\x00\x03Y[\xdb\xb6\x0e~N~\x05Vv:=6M:uShkJTD\xca\xbb>\x00\xc8\x92,Yn \x0f\x04\t\x10F
    aaaa007cn
        3
    aaaa007cn  
       2015-04-01 21:21:26 +08:00   ❤️ 1
    请贴出网页地址先
    soratadori
        4
    soratadori  
    OP
       2015-04-02 02:36:04 +08:00
    @aaaa007cn anidb.net,这个网站有反机器人的措施,请把请求头传送完整,不然有可能会被ban
    aaaa007cn
        5
    aaaa007cn  
       2015-04-03 00:56:04 +08:00   ❤️ 1
    服务器返回的是 gzip 压缩过的内容
    即使请求中没有设定 Accept-Encoding 头

    >>> import urllib.request
    >>> r = urllib.request.urlopen('http://anidb.net/perl-bin/animedb.pl?show=main')
    >>> r.getheader('Content-Encoding')
    'gzip'

    所以需要自行 gzip,如果你用 urllib 的话
    >>> import gzip
    >>> data = r.read()
    >>> gzip.decompress(data)
    b'<!DOCTYPE html>\n<html...

    再次进行 decode 就可以得到 unicode 字符串
    >>> gzip.decompress(data).decode('utf-8')
    '<!DOCTYPE html>\n<html...

    或者使用 requests
    它会检查相关的 http 头然后自动解压并尝试自动解码
    >>> import requests
    >>> r = requests.get('http://anidb.net/perl-bin/animedb.pl?show=main')
    >>> r.text
    '<!DOCTYPE html>\n<html...
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2716 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 07:01 · PVG 15:01 · LAX 23:01 · JFK 02:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.