UnicodeEncodeError:'ascii' 编解码器无法对位置 20 处的字符 u'\xa0' 进行编码:序数不在范围内(128)

2024-11-20 08:44:00
admin
原创
7
摘要:问题描述:我在处理从不同网页(不同网站)获取的文本中的 unicode 字符时遇到了问题。我正在使用 BeautifulSoup。问题是错误并不总是可重现的;它有时适用于某些页面,有时,它会抛出一个错误UnicodeEncodeError。我已经尝试了几乎所有我能想到的方法,但我还没有找到任何可以持续工作而不...

问题描述:

我在处理从不同网页(不同网站)获取的文本中的 unicode 字符时遇到了问题。我正在使用 BeautifulSoup。

问题是错误并不总是可重现的;它有时适用于某些页面,有时,它会抛出一个错误UnicodeEncodeError。我已经尝试了几乎所有我能想到的方法,但我还没有找到任何可以持续工作而不会抛出某种与 Unicode 相关的错误的方法。

导致问题的代码部分如下所示:

agent_telno = agent.find('div', 'agent_contact_number')
agent_telno = '' if agent_telno is None else agent_telno.contents[0]
p.agent_info = str(agent_contact + ' ' + agent_telno).strip()

这是运行上述代码片段时对某些字符串生成的堆栈跟踪:

Traceback (most recent call last):
  File "foobar.py", line 792, in <module>
    p.agent_info = str(agent_contact + ' ' + agent_telno).strip()
UnicodeEncodeError: 'ascii' codec can't encode character u'xa0' in position 20: ordinal not in range(128)

我怀疑这是因为某些页面(或者更具体地说,某些网站的页面)可能经过编码,而其他页面可能未经过编码。所有网站都位于英国,提供的数据供英国使用 - 因此不存在与内部化或处理以非英语编写的文本相关的问题。

有人知道如何解决这个问题,以便我可以始终如一地解决这个问题?


解决方案 1:

阅读 Python Unicode HOWTO。这个错误就是第一个例子。

不要用于str()从unicode转换为编码文本/字节。

相反,使用.encode()来编码字符串:

p.agent_info = u' '.join((agent_contact, agent_telno)).encode('utf-8').strip()

或者完全使用unicode工作。

解决方案 2:

这是典型的 Python unicode 痛点!考虑以下几点:

a = u'bats/u00E0'
print a
 => batsà

到目前为止一切都很好,但如果我们调用 str(a),让我们看看会发生什么:

str(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'xe0' in position 4: ordinal not in range(128)

哦,这可不会给任何人带来任何好处!要修复此错误,请使用 .encode 明确编码字节,并告诉 python 要使用哪种编解码器:

a.encode('utf-8')
 => 'batsxc3xa0'
print a.encode('utf-8')
 => batsà

瞧!

问题是,当您调用 str() 时,python 使用默认字符编码来尝试编码您提供的字节,在您的情况下,这些字节有时是 unicode 字符的表示。要解决此问题,您必须使用 .encode('whatever_unicode') 告诉 python 如何处理您提供的字符串。大多数情况下,使用 utf-8 应该没问题。

有关该主题的出色阐述,请参阅 Ned Batchelder 的 PyCon 演讲:http: //nedbatchelder.com/text/unipain.html

解决方案 3:

我发现了一个优雅的解决方法,可以删除符号并继续将字符串保留为字符串,如下所示:

yourstring = yourstring.encode('ascii', 'ignore').decode('ascii')

值得注意的是,使用 ignore 选项是危险的,因为它会默默地从使用它的代码中删除任何 unicode(和国际化)支持,如下所示(转换 unicode):

>>> u'City: Malmö'.encode('ascii', 'ignore').decode('ascii')
'City: Malm'

解决方案 4:

好吧,我尝试了所有方法但没有帮助,在谷歌搜索之后,我发现了以下内容并且有所帮助。正在使用 python 2.7。

# encoding=utf8
import sys
reload(sys)
sys.setdefaultencoding('utf8')

解决方案 5:

导致打印失败的一个细微问题是环境变量设置错误,例如,此处 LC_ALL 设置为“C”。在 Debian 中,他们不鼓励设置它:Debian wiki 上的 Locale

$ echo $LANG
en_US.utf8
$ echo $LC_ALL 
C
$ python -c "print (u'voil/u00e0')"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'xe0' in position 4: ordinal not in range(128)
$ export LC_ALL='en_US.utf8'
$ python -c "print (u'voil/u00e0')"
voilà
$ unset LC_ALL
$ python -c "print (u'voil/u00e0')"
voilà

解决方案 6:

问题是您正在尝试打印一个 unicode 字符,但是您的终端不支持它。

您可以尝试安装language-pack-en包来修复该问题:

sudo apt-get install language-pack-en

它为所有受支持的软件包(包括 Python)提供英语翻译数据更新。如有必要,请安装不同的语言包(取决于您要打印的字符)。

在某些 Linux 发行版中,需要安装它以确保默认英语区域设置正确设置(以便 shell/终端可以处理 unicode 字符)。有时安装它比手动配置它更容易。

然后在编写代码时,确保在代码中使用正确的编码。

例如:

open(foo, encoding='utf-8')

如果仍然有问题,请仔细检查您的系统配置,例如:

  • 您的语言环境文件 ( /etc/default/locale),其中应该包含例如

LANG="en_US.UTF-8"
LC_ALL="en_US.UTF-8"

或者:

LC_ALL=C.UTF-8
LANG=C.UTF-8
  • LANG外壳程序中/的值LC_CTYPE

  • 通过以下方式检查你的 shell 支持哪个语言环境:

locale -a | grep "UTF-8"

在全新 VM 中演示问题和解决方案。

  1. 初始化并配置虚拟机(例如使用vagrant):

vagrant init ubuntu/trusty64; vagrant up; vagrant ssh

参见:可用的Ubuntu盒子。

  1. 打印unicode字符(例如商标符号):

$ python -c 'print(u"/u2122");'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'/u2122' in position 0: ordinal not in range(128)
  1. 现在安装language-pack-en

$ sudo apt-get -y install language-pack-en
The following extra packages will be installed:
  language-pack-en-base
Generating locales...
  en_GB.UTF-8... /usr/sbin/locale-gen: done
Generation complete.
  1. 现在问题应该解决了:

$ python -c 'print(u"/u2122");'
™
  1. 否则,请尝试以下命令:

$ LC_ALL=C.UTF-8 python -c 'print(u"/u2122");'
™

解决方案 7:

在 shell 中:

  1. 通过以下命令查找支持的 UTF-8 语言环境:

locale -a | grep "UTF-8"
  1. 在运行脚本之前将其导出,例如:

export LC_ALL=$(locale -a | grep UTF-8)

或者手动操作:

export LC_ALL=C.UTF-8
  1. 通过打印特殊字符来测试它,例如

python -c 'print(u"/u2122");'

以上已在 Ubuntu 中测试。

解决方案 8:

事实上我发现在大多数情况下,删除这些字符要简单得多:

s = mystring.decode('ascii', 'ignore')

解决方案 9:

对我来说,有效的方法是:

BeautifulSoup(html_text,from_encoding="utf-8")

希望这对某人有帮助。

解决方案 10:

以下是一些其他所谓“逃避”答案的重述。在某些情况下,尽管有人提出抗议,但简单地丢弃麻烦的字符/字符串是一种好的解决方案。

def safeStr(obj):
    try: return str(obj)
    except UnicodeEncodeError:
        return obj.encode('ascii', 'ignore').decode('ascii')
    except: return ""

测试:

if __name__ == '__main__': 
    print safeStr( 1 ) 
    print safeStr( "test" ) 
    print u'98xb0'
    print safeStr( u'98xb0' )

结果:

1
test
98°
98

更新:我原来的答案是针对 Python 2 编写的。对于Python 3

def safeStr(obj):
    try: return str(obj).encode('ascii', 'ignore').decode('ascii')
    except: return ""

注意:如果您希望?在“不安全”的Unicode字符处留下指示,请在错误处理程序的编码调用中指定replace而不是。ignore

建议:您可能想toAscii改用其他名称来命名此函数?这只是个人喜好问题...

最后,这是一个使用 的更强大的 PY2/3 版本six,其中我选择使用replace,并加入一些字符交换,以使用简单的垂直字符(ascii 集的一部分)替换向左或向右卷曲的花哨 unicode 引号和撇号。您可以自己扩展此类交换:

from six import PY2, iteritems 

CHAR_SWAP = { u'/u201c': u'"'
            , u'/u201D': u'"' 
            , u'/u2018': u"'" 
            , u'/u2019': u"'" 
}

def toAscii( text ) :    
    try:
        for k,v in iteritems( CHAR_SWAP ): 
            text = text.replace(k,v)
    except: pass     
    try: return str( text ) if PY2 else bytes( text, 'replace' ).decode('ascii')
    except UnicodeEncodeError:
        return text.encode('ascii', 'replace').decode('ascii')
    except: return ""

if __name__ == '__main__':     
    print( toAscii( u'testin/u2019' ) )

解决方案 11:

在脚本的开头添加以下行(或作为第二行):

# -*- coding: utf-8 -*-

这是 Python 源代码编码的定义。更多信息请参阅PEP 263。

解决方案 12:

我总是将下面的代码放在 python 文件的前两行:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

解决方案 13:

它对我有用:

export LC_CTYPE="en_US.UTF-8"

解决方案 14:

唉,这至少在 Python 3 中有效......

Python 3

有时错误是在环境变量和编码中

import os
import locale
os.environ["PYTHONIOENCODING"] = "utf-8"
myLocale=locale.setlocale(category=locale.LC_ALL, locale="en_GB.UTF-8")
... 
print(myText.encode('utf-8', errors='ignore'))

在编码过程中,错误会被忽略。

解决方案 15:

如果是打印语句的问题,很多时候只是终端打印的问题。这对我有帮助:
export PYTHONIOENCODING=UTF-8

解决方案 16:

简单的辅助函数可以在这里找到。

def safe_unicode(obj, *args):
    """ return the unicode representation of obj """
    try:
        return unicode(obj, *args)
    except UnicodeDecodeError:
        # obj is byte string
        ascii_text = str(obj).encode('string_escape')
        return unicode(ascii_text)

def safe_str(obj):
    """ return the byte string representation of obj """
    try:
        return str(obj)
    except UnicodeEncodeError:
        # obj is unicode
        return unicode(obj).encode('unicode_escape')

解决方案 17:

只需添加到变量编码('utf-8')

agent_contact.encode('utf-8')

解决方案 18:

请打开终端并执行以下命令:

export LC_ALL="en_US.UTF-8"

解决方案 19:

回答晚了,但这个错误与你的终端编码不支持某些字符有关。

python3使用以下方法修复了它:

import sys
import io

sys.stdout = io.open(sys.stdout.fileno(), 'w', encoding='utf8')
print("é, à, ...")

解决方案 20:

我刚刚使用了以下内容:

import unicodedata
message = unicodedata.normalize("NFKD", message)

检查一下文档中关于它的内容:

unicodedata.normalize(form, unistr) 返回 Unicode 字符串 unistr 的正常形式 form。form 的有效值为“NFC”、“NFKC”、“NFD”和“NFKD”。

Unicode 标准根据规范等价性和兼容性等价性定义,定义了 Unicode 字符串的各种规范化形式。在 Unicode 中,多个字符可以用各种方式表示。例如,字符 U+00C7(带下划线的拉丁大写字母 C)也可以表示为序列 U+0043(带下划线的拉丁大写字母 C)U+0327(组合下划线)。

对于每个字符,有两种范式:范式 C 和范式 D。范式 D (NFD) 也称为规范分解,将每个字符转换为其分解形式。范式 C (NFC) 首先应用规范分解,然后再次组合预先组合的字符。

除了这两种形式外,还有两种基于兼容性等价性的附加范式。Unicode 支持某些字符,这些字符通常会与其他字符统一。例如,U+2160(罗马数字 1)实际上与 U+0049(拉丁大写字母 I)相同。但是,Unicode 支持它以兼容现有字符集(例如 gb2312)。

范式 KD (NFKD) 将应用兼容性分解,即用等价字符替换所有兼容性字符。范式 KC (NFKC) 首先应用兼容性分解,然后应用规范组合。

即使两个 Unicode 字符串经过规范化,对人类读者来说看起来相同,但如果其中一个具有组合字符而另一个没有,则它们可能无法进行比较。

帮我解决了。简单又容易。

解决方案 21:

下面的解决方案对我有用,刚刚添加

u “字符串”

(将字符串表示为unicode)在我的字符串之前。

result_html = result.to_html(col_space=1, index=False, justify={'right'})

text = u"""
<html>
<body>
<p>
Hello all, <br>
<br>
Here's weekly summary report.  Let me know if you have any questions. <br>
<br>
Data Summary <br>
<br>
<br>
{0}
</p>
<p>Thanks,</p>
<p>Data Team</p>
</body></html>
""".format(result_html)

解决方案 22:

推荐的解决方案对我来说不起作用,我可以忍受转储所有非 ascii 字符,所以

s = s.encode('ascii',errors='ignore')

这让我得到了一些不会引发错误的东西。

解决方案 23:

在将不受支持的编码 字符串(比如说data_that_causes_this_error)写入某个文件(例如)的一般情况下results.txt,这是可行的

f = open("results.txt", "w")
  f.write(data_that_causes_this_error.encode('utf-8'))
  f.close()

解决方案 24:

我刚刚遇到了这个问题,然后谷歌引导我到了这里,所以只是为了补充这里的一般解决方案,这是对我有用的:

# 'value' contains the problematic data
unic = u''
unic += value
value = unic

在阅读了Ned 的演讲后我有了这个想法。

不过,我并不声称完全理解为什么这样做有效。因此,如果有人可以编辑此答案或发表评论进行解释,我将不胜感激。

解决方案 25:

manage.py migrate我们在使用本地化装置在 Django 中运行时遇到了这个错误。

我们的源包含# -*- coding: utf-8 -*-声明,MySQL 已正确配置为 utf8,并且 Ubuntu 具有适当的语言包和值/etc/default/locale

问题很简单,Django 容器(我们使用 docker)缺少LANG环境变量。

在重新运行迁移之前设置并LANG重新en_US.UTF-8启动容器可以解决问题。

解决方案 26:

更新至 Python 3.0 及更高版本。在 Python 编辑器中尝试以下操作:

locale-gen en_US.UTF-8
export LANG=en_US.UTF-8 LANGUAGE=en_US.en
LC_ALL=en_US.UTF-8

这会将系统的默认区域编码设置为 UTF-8 格式。

更多内容可以参阅此处 PEP 538——将传统 C 语言环境强制转换为基于 UTF-8 的语言环境。

解决方案 27:

这里的许多答案(例如@agf 和@Andbdrew)已经解决了 OP 问题的最直接方面。

然而,我认为有一个微妙但重要的方面在很大程度上被忽略了,而对于像我一样试图理解 Python 编码的人来说,这一点非常重要:Python 2 和 Python 3 对字符表示的管理截然不同。我觉得造成这种困惑的很大一部分原因是人们在阅读 Python 编码时不了解版本。

我建议任何有兴趣了解 OP 问题根本原因的人首先阅读Spolsky 的字符表示和 Unicode 简介,然后转到Python 2 和 Python 3 中的 Unicode 上的Batchelder 。

解决方案 28:

尽量避免将变量转换为 str(variable)。有时,这可能会导致问题。

简单的避免技巧:

try: 
    data=str(data)
except:
    data = data #Don't convert to String

上面的例子也将解决编码错误。

解决方案 29:

如果有类似的内容packet_data = "This is data",请在初始化之后在下一行执行以下操作packet_data

unic = u''
packet_data = unic

解决方案 30:

当使用 Apache 部署 django 项目时,经常会发生此问题。因为 Apache 在 /etc/sysconfig/httpd 中设置了环境变量 LANG=C。只需打开文件并注释(或更改为您的风格)此设置。或者使用 WSGIDaemonProcess 命令的 lang 选项,在这种情况下,您将能够为不同的虚拟主机设置不同的 LANG 环境变量。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用