求助:被 python 的编码搞疯了

2016-06-04 11:15:44 +08:00
 lovebeyondalways

小弟用的是 python3.5 ,听说 python3 解决了编码问题
然而
import urllib.request
html = urllib.request.urlopen('http://www.baidu.com').read().decode('utf-8')
print(html)

结果:
Traceback (most recent call last):
File ".\Desktop\work\wearther.py", line 3, in <module>
print(html)
UnicodeEncodeError: 'gbk' codec can't encode character '\xbb' in position 25395: illegal multibyte sequence

这样也不行.decode('utf-8').encode('utf-8')
所以新手求助啊

9501 次点击
所在节点    Python
45 条回复
276562578
2016-06-04 11:19:46 +08:00
先看看是什么格式的编码,用 chardet 库,然后再 de 和 en
GPU
2016-06-04 11:24:33 +08:00
不是应该用 requests 吗?

腰不酸腿不疼
SuperMild
2016-06-04 11:24:34 +08:00
可能是 Windows 的坑
janxin
2016-06-04 11:28:59 +08:00
试了一下没有问题啊,你这是 Windows 的坑吧
a412739861
2016-06-04 11:29:56 +08:00
我用 requests 似乎需要设置这个的,直接能够打开 gbk 的。
只是在 post 数据的时候,要 encode 成对应的编码,这个地方要自己写。
lovebeyondalways
2016-06-04 11:29:59 +08:00
@janxin 我靠 windows 这坑怎么跳过
Sylv
2016-06-04 11:29:59 +08:00
Python 3 的字符串已经是 unicode 了,你为什么还要 decode ?
基础知识:
unicode.encode(encoding) -> bytes
bytes.decode(encoding) -> unicode
unicode.decode(encoding) -> unicode.encode(defaultencoding).decode(encoding) -> unicode

Python 3 是解决了部分 Python 2 的编码坑,但并不代表不再需要掌握基础的编码知识了。
uniquecolesmith
2016-06-04 11:42:19 +08:00
你对编码的理解反了, unicode 是字符集,是规范,而 utf-8 是 unicode 的一种实现。或者你可以理解为 unicode 是非可视编码,而 utf-8 是可视编码,所以应该是个 encode('utf-8')才可行
annielong
2016-06-04 11:43:00 +08:00
大坑, windows+中文,回回都要被编码坑一下,
uniquecolesmith
2016-06-04 11:47:42 +08:00
补充 没记错的话, windows 下应该 urllib.request.urlopen('http://www.baidu.com').read().encode('cp936')或者其他
xiandao7997
2016-06-04 11:51:04 +08:00
@lovebeyondalways 在 iV2 结果基本上就是劝你换 mac :)
以前也遇到这个坑,跟别人回复的一样,数据获取到了用 chardet 先检测一下编码,然后再 decode/encode, win 命令行里输出的话 utf8 貌似是不行的,只可以用 unicode/gb2312/gbk/cp936 ,记不清了,你可以再试试~
congeec
2016-06-04 12:02:28 +08:00
不是 Python 坑你,是 Terminal 坑你。你的代码我在 OS X 下执行就没问题。 Windows ,如果我没记错的话,用 UCS-2/GBK 处理中文。你的 Terminal (应该是 cmd.exe 吧)有没有用 UTF-8 ?
Delbert
2016-06-04 12:09:35 +08:00
win 的 cmd 是 cp936 , unicode 是 65001(印象中是这个)
YuJianrong
2016-06-04 12:10:42 +08:00
这个原因很容易理解吧?主要有两点
1. GBK 没有完全覆盖 unicode ,有些 unicode 字符无法编码成 GBK
2. windows 版本的 print 在中文 windows 环境下输出需要编译成环境编码也就是 cp936 , python 视 cp936 等同 GBK (这也没错)

所以其实是 print 的锅,你不如把字符串编码成 utf8 存文件来看好了,不要 print 。
21grams
2016-06-04 12:15:05 +08:00
我用的还是 2.7 , 更痛苦,尤其在 windows 下,简直噩梦。
cosven
2016-06-04 12:44:03 +08:00
@YuJianrong 正解

看它报错的位置嘛,说的是第三行,而不是第二行的 decode 有错,而楼上许多人都在分析 decode('utf-8') 这句有错。显然没有抓住问题关键。

windows cmd 下 print 会把字符串转换成 gbk 编码来输出,所以才会有 LZ 现在遇到的问题。

>>> html.encode('gbk') # 说明 html 这个字符串中有些字符不能编码成 gbk
UnicodeEncodeError: 'gbk' codec can't encode character '\xbb' in position 25395: illegal multibyte sequence

*****所以, LZ 的问题,并不是单纯的不能输出中文的问题*****

解决办法
1. 如 YuJianrong 所说:把它输出到文件是一种办法
2. 参考这篇博客,貌似可以输出到 cmd: http://blog.csdn.net/jim7424994/article/details/22675759

---------题外话(关于 cmd python3 输出中文)-------------------
参考 http://www.crifan.com/python_3_x_auto_handle_string_encode_and_decode_to_and_from_unicode_then_output_to_cmd/ 这篇博客,对 windows 下 python3 输出中文的一些情况作了测试。

----------------------------------------------------------------------------

@Sylv urlopen('http://www.baidu.com').read() 之后的对象是 bytes ,不是字符串
@uniquecolesmith bytes 对象应该 decode 成 utf-8 ,而不是 encode
walleL
2016-06-04 13:25:02 +08:00
做了一些测试,我来整理一下吧(我用的 python2.7)

1. content = urllib.request.urlopen('http://www.baidu.com').read() # 得到 bytes
2. text = content.decode('utf8') # 得到 unicode(这里已确定 content 为 utf8 编码)
3. print(text) # print 时 python 会根据当前 sys.stdout 的编码对 text 进行 encode, win 下 stdout 的编码是 gbk ,而有些 unicode 无法编码为 gbk ,所以报错

解决方案:
1. @cosven 的回复中提到的博客里的方法:改 sys.stdout 的编码
2. 先 encode 为 gbk ,并指定 errors='replace' (当遇到不可编码字符时使用 ? 替换), 然后 print:
print(text.encode('gbk', errors='replace')) #不推荐,无法解码的字符可能就成 ? 了
3. 结合 1,2: print(text.encode('gp18030'))
lovebeyondalways
2016-06-04 13:25:47 +08:00
@cosven
@YuJianrong 感谢 确实是 print 的问题
cosven
2016-06-04 13:27:21 +08:00
事后又仔细阅读了 http://blog.csdn.net/jim7424994/article/details/22675759 这篇博文,它使用 GB18030 编码可以成功输出。

所以我猜(手上并没有 windows ): print(html.encode('gb18030')) 应该是可以正常输出的

参考: gbk 编码都多种: GB2312, GB18030, GBK https://www.zhihu.com/question/19677619
daimoon
2016-06-04 14:11:28 +08:00
简单的办法,把 python 安装目录中的 site.py 里面的 del sys.setdefaultencoding ,替换为 sys.setdefaultencoding("utf-8").
以后就没问题了。

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

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

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

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

© 2021 V2EX