我的代码只是抓取一个网页,然后将其转换为 Unicode。
html = urllib.urlopen(link).read()
html.encode("utf8","ignore")
self.response.out.write(html)
但我得到一个 UnicodeDecodeError
:
Traceback (most recent call last):
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/webapp/__init__.py", line 507, in __call__
handler.get(*groups)
File "/Users/greg/clounce/main.py", line 55, in get
html.encode("utf8","ignore")
UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 2818: ordinal not in range(128)
我认为这意味着 HTML 在某处包含一些格式错误的 Unicode 尝试。我可以只删除导致问题的任何代码字节而不是出错吗?
c2
字节开头,否则您可能会收到解码错误:hexutf8.com/?q=C2A0
\x1b[38;5;226m...
它是 ansi escape codes,而不是 unicode。
>>> u'aあä'.encode('ascii', 'ignore')
'a'
使用响应中相应 meta
标记或 Content-Type
标头中的字符集对您返回的字符串进行解码,然后进行编码。
方法 encode(encoding, errors)
接受错误的自定义处理程序。除 ignore
外,默认值为:
>>> u'aあä'.encode('ascii', 'replace')
b'a??'
>>> u'aあä'.encode('ascii', 'xmlcharrefreplace')
b'aあä'
>>> u'aあä'.encode('ascii', 'backslashreplace')
b'a\\u3042\\xe4'
请参阅https://docs.python.org/3/library/stdtypes.html#str.encode
作为 Ignacio Vazquez-Abrams 回答的延伸
>>> u'aあä'.encode('ascii', 'ignore')
'a'
有时需要从字符中删除重音符号并打印基本形式。这可以通过
>>> import unicodedata
>>> unicodedata.normalize('NFKD', u'aあä').encode('ascii', 'ignore')
'aa'
您可能还想将其他字符(如标点符号)翻译成最接近的等价物,例如,在编码时,右单引号 unicode 字符不会转换为 ascii APOSTROPHE。
>>> print u'\u2019'
’
>>> unicodedata.name(u'\u2019')
'RIGHT SINGLE QUOTATION MARK'
>>> u'\u2019'.encode('ascii', 'ignore')
''
# Note we get an empty string back
>>> u'\u2019'.replace(u'\u2019', u'\'').encode('ascii', 'ignore')
"'"
尽管有更有效的方法来实现这一点。有关详细信息,请参阅此问题 Where is Python's "best ASCII for this Unicode" database?
2018 年更新:
截至 2018 年 2 月,使用 gzip
之类的压缩已成为 quite popular(大约 73% 的所有网站都在使用它,包括 Google、YouTube、Yahoo、Wikipedia、Reddit、Stack Overflow 和 Stack Exchange Network 网站等大型网站)。< br> 如果您在原始答案中使用 gzip 响应进行简单解码,您将收到类似或类似以下的错误:
UnicodeDecodeError:“utf8”编解码器无法解码位置 1 的字节 0x8b:意外的代码字节
为了解码 gzpipped 响应,您需要添加以下模块(在 Python 3 中):
import gzip
import io
注意: In Python 2 you'd use StringIO
instead of io
然后你可以像这样解析内容:
response = urlopen("https://example.com/gzipped-ressource")
buffer = io.BytesIO(response.read()) # Use StringIO.StringIO(response.read()) in Python 2
gzipped_file = gzip.GzipFile(fileobj=buffer)
decoded = gzipped_file.read()
content = decoded.decode("utf-8") # Replace utf-8 with the source encoding of your requested resource
此代码读取响应,并将字节放入缓冲区。 gzip
模块然后使用 GZipFile
函数读取缓冲区。之后,可以再次将 gzip 压缩文件读入字节并最终解码为正常可读的文本。
2010年的原始答案:
我们能得到用于 link
的实际值吗?
另外,当我们试图.encode()
一个已经编码的字节串时,我们通常会在这里遇到这个问题。所以你可能会尝试先解码它,如
html = urllib.urlopen(link).read()
unicode_str = html.decode(<source encoding>)
encoded_str = unicode_str.encode("utf8")
举个例子:
html = '\xa0'
encoded_str = html.encode("utf8")
失败
UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 0: ordinal not in range(128)
尽管:
html = '\xa0'
decoded_str = html.decode("windows-1252")
encoded_str = decoded_str.encode("utf8")
成功无误。请注意,“windows-1252”是我用作示例的东西。我从 chardet 得到这个,它有 0.5 的信心认为它是正确的! (好吧,正如给出的 1 个字符长度的字符串,您期望什么)您应该将其更改为从 .urlopen().read()
返回的字节字符串的编码,以适用于您检索的内容。
我看到的另一个问题是 .encode()
字符串方法返回修改后的字符串并且没有修改源。因此,拥有 self.response.out.write(html)
是没有用的,因为 html 不是来自 html.encode 的编码字符串(如果那是您最初的目标)。
正如 Ignacio 建议的那样,检查源网页以了解从 read()
返回的字符串的实际编码。它位于 Meta 标记之一或响应的 ContentType 标头中。然后将其用作 .decode()
的参数。
但是请注意,不应假定其他开发人员有足够的责任来确保标头和/或元字符集声明与实际内容匹配。 (这是一个 PITA,是的,我应该知道,我以前是其中之一)。
encoded_str = decoded_str.encode("utf8")
raise IOError, 'Not a gzipped file'
。我做错了什么?
使用 unidecode - 它甚至可以将奇怪的字符立即转换为 ascii,甚至将中文转换为拼音 ascii。
$ pip install unidecode
然后:
>>> from unidecode import unidecode
>>> unidecode(u'北京')
'Bei Jing'
>>> unidecode(u'Škoda')
'Skoda'
我在所有项目中都使用这个辅助函数。如果它不能转换 unicode,它会忽略它。这与 django 库有关,但稍加研究您就可以绕过它。
from django.utils import encoding
def convert_unicode_to_string(x):
"""
>>> convert_unicode_to_string(u'ni\xf1era')
'niera'
"""
return encoding.smart_str(x, encoding='ascii', errors='ignore')
使用它后,我不再收到任何 unicode 错误。
对于 cmd.exe
和 HTML 输出等损坏的控制台,您始终可以使用:
my_unicode_string.encode('ascii','xmlcharrefreplace')
这将保留所有非 ascii 字符,同时使它们可以在纯 ASCII 和 HTML 中打印。
警告:如果您在生产代码中使用它来避免错误,那么您的代码很可能有问题。唯一有效的用例是打印到非 unicode 控制台或在 HTML 上下文中轻松转换为 HTML 实体。
最后,如果您在 Windows 上使用 cmd.exe,则可以键入 chcp 65001
以启用 utf-8 输出(使用 Lucida Console 字体)。您可能需要添加 myUnicodeString.encode('utf8')
。
你写了“”“我认为这意味着 HTML 在某处包含一些格式错误的 unicode 尝试。”“”
HTML 不应包含任何类型的“尝试 unicode”,无论格式是否正确。它必须包含以某种编码方式编码的 Unicode 字符,这通常是预先提供的……寻找“字符集”。
您似乎假设字符集是 UTF-8 ...基于什么理由?错误消息中显示的“\xA0”字节表明您可能有一个单字节字符集,例如 cp1252。
如果您无法理解 HTML 开头的声明,请尝试使用 chardet 找出可能的编码是什么。
为什么你用“正则表达式”标记你的问题?
用非问题替换整个问题后更新:
html = urllib.urlopen(link).read()
# html refers to a str object. To get unicode, you need to find out
# how it is encoded, and decode it.
html.encode("utf8","ignore")
# problem 1: will fail because html is a str object;
# encode works on unicode objects so Python tries to decode it using
# 'ascii' and fails
# problem 2: even if it worked, the result will be ignored; it doesn't
# update html in situ, it returns a function result.
# problem 3: "ignore" with UTF-n: any valid unicode object
# should be encodable in UTF-n; error implies end of the world,
# don't try to ignore it. Don't just whack in "ignore" willy-nilly,
# put it in only with a comment explaining your very cogent reasons for doing so.
# "ignore" with most other encodings: error implies that you are mistaken
# in your choice of encoding -- same advice as for UTF-n :-)
# "ignore" with decode latin1 aka iso-8859-1: error implies end of the world.
# Irrespective of error or not, you are probably mistaken
# (needing e.g. cp1252 or even cp850 instead) ;-)
如果您有字符串 line
,则可以使用字符串的 .encode([encoding], [errors='strict'])
方法来转换编码类型。
line = 'my big string'
line.encode('ascii', 'ignore')
有关在 Python 中处理 ASCII 和 unicode 的更多信息,这是一个非常有用的站点:https://docs.python.org/2/howto/unicode.html
我认为答案就在那里,但只是零碎的,这使得很难快速解决问题,例如
UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 2818: ordinal not in range(128)
举个例子,假设我有一个文件,其中包含以下形式的一些数据(包含 ascii 和非 ascii 字符)
2017 年 1 月 10 日,21:36 - 土地:欢迎 ��
我们想忽略并只保留 ascii 字符。
此代码将执行以下操作:
import unicodedata
fp = open(<FILENAME>)
for line in fp:
rline = line.strip()
rline = unicode(rline, "utf-8")
rline = unicodedata.normalize('NFKD', rline).encode('ascii','ignore')
if len(rline) != 0:
print rline
和 type(rline) 会给你
>type(rline)
<type 'str'>
unicodestring = '\xa0'
decoded_str = unicodestring.decode("windows-1252")
encoded_str = decoded_str.encode('ascii', 'ignore')
为我工作
您可以使用以下代码作为示例来避免 Unicode 到 ASCII 错误:
from anyascii import anyascii
content = "Base Rent for – CC# 2100 Acct# 8410: $41,667.00 – PO – Lines - for Feb to Dec to receive monthly"
content = anyascii(content)
print(content)
看起来你正在使用 python 2.x。 Python 2.x 默认为 ascii,它不知道 Unicode。因此例外。
只需在shebang之后粘贴以下行,它就会起作用
# -*- coding: utf-8 -*-
coding
评论不是万灵药。你需要知道为什么会产生错误,这只会在你的 Python 源代码中有坏字符时修复问题。对于这个问题,情况似乎并非如此。
不定期副业成功案例分享
iconv
或任何其他i = orig.find(x); if i >= 0: x = dest[I]
都没有解决方案,其中original
类似于:origL = 'áéíóúüç'
和dest=destL = 'aeiouuc'