【问题标题】:Python 3.x about encodingPython 3.x 关于编码
【发布时间】:2016-11-03 08:45:51
【问题描述】:
# -*- coding: utf-8 -*-

import urllib.request as request

import re

url = "http://jjo.kr/users/38281748"

raw_data = request.urlopen(url).read() #Bytes

decoded = raw_data.decode("utf-8")

print(decoded)

我试图获取有关该网址的 HTML 信息,但收到错误消息。

UnicodeEncodeError: 'cp949' codec can't encode character '\ufeff' in position 2313: 非法多字节序列

我是不是误解了decode()这个功能?

根据 Python 3.5.2 标准库 decode “返回从给定字节解码的字符串。”。

但我得到的是 cp949 而不是 utf-8 字符串。

谁能告诉我我的代码有什么问题?

【问题讨论】:

  • 异常来自哪一行?我假设它来自印刷品,它试图转换为 cp949 以与您的终端一起使用?

标签: python python-3.x encoding utf-8


【解决方案1】:

你已经通过解码字节字符串得到了 unicode 字符串。

但是当你尝试打印它时,python 使用 cp949 编码(因为它是你的标准输出编码 = sys.stdout.encoding

\ufeff(零宽度无间隔)不能用cp949编码表示。

>>> import unicodedata
>>> unicodedata.name('\ufeff')
'ZERO WIDTH NO-BREAK SPACE'

您可以通过使用ignorereplace 错误处理程序进行编码来忽略/替换此类字符。

import sys

decoded = raw_data.decode("utf-8")
decoded = decoded.encode(sys.stdout.encoding, 'ignore').decode(sys.stdout.encoding)
print(decoded)

【讨论】:

  • 这是对的,只是为什么要先编码成stdout的编码,然后再解码?
  • 天哪,它确实有效!你一定是天才。谢谢你解决了我的问题。
  • @RemcoGerlich,您需要使用标准输出的编码(print(..) 时使用)进行编码。否则,它将像 OP 一样引发 UnicodeEncodeError。不解码,尤其是在 Python 3 中,它会打印出不需要的b'...'(Python 3.x 的字节对象表示)
【解决方案2】:

解码后的字符串包含一个\uFEFF 字符,这是一个字节顺序标记。我不知道为什么它会出现在页面中间,但是编码它不起作用。

删除它:

decoded = decoded.replace('\ufeff', '')

它可能会起作用。

【讨论】:

  • 非常感谢!但我认为 \ufeff 不是唯一导致错误的原因。
  • @JakSa:不幸的是我无法测试,因为我没有安装 cp949 编码。 falsetru 的回答更笼统。
  • u'\ufeff' != b'\xfeff'
  • '\ufeff' 不是 BOM,而是 ZERO WIDTH NO-BREAK SPACE
  • @falsetru:我认为在更高版本的 Unicode 中发生了变化,en.wikipedia.org/wiki/Byte_order_mark:“如果 BOM 字符出现在数据流的中间,Unicode 表示它应该被解释为“零-宽度不间断空格”(禁止字形之间的换行)。在 Unicode 3.2 中,不推荐使用这种用法,而支持“Word Joiner”字符 U+2060。[1] 这仅允许 U+FEFF用作 BOM。”
猜你喜欢
  • 1970-01-01
  • 2015-09-02
  • 1970-01-01
  • 2013-10-17
  • 2019-09-27
  • 2011-11-14
  • 2010-09-15
  • 2020-05-15
  • 1970-01-01
相关资源
最近更新 更多