ChatGPT解决这个技术问题 Extra ChatGPT

UnicodeEncodeError:“charmap”编解码器无法编码字符

我正在尝试抓取一个网站,但它给了我一个错误。

我正在使用以下代码:

import urllib.request
from bs4 import BeautifulSoup

get = urllib.request.urlopen("https://www.website.com/")
html = get.read()

soup = BeautifulSoup(html)

print(soup)

我收到以下错误:

File "C:\Python34\lib\encodings\cp1252.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode characters in position 70924-70950: character maps to <undefined>

我能做些什么来解决这个问题?


t
twasbrillig

将抓取的网络内容保存到文件时,我得到了相同的 UnicodeEncodeError。为了修复它,我替换了这段代码:

with open(fname, "w") as f:
    f.write(html)

有了这个:

with open(fname, "w", encoding="utf-8") as f:
    f.write(html)

如果您需要支持 Python 2,请使用以下命令:

import io
with io.open(fname, "w", encoding="utf-8") as f:
    f.write(html)

如果您的文件以非 UTF-8 编码,请指定 encoding 的实际编码。


在 mac(python 3) 中,只需打开而无需编码即可完美运行,但在 windows(w10, python3) 中不是一个选项。以这种方式工作,使用 encoding="utf-8" 参数。
谢谢你。它对我有用,我正在处理 xml 文件并将 xml.toprettyxml() 的结果写入一个新文件
这应该是公认的答案,因为它最终会将字符串写入输出,而不是字节的字符串表示。
但是,OP 请求读取文件,而不是写入文件。这个问题似乎与控制台有关。
@EcksDee 的评论与此答案的早期版本有关。当前版本是正确的; io 包装器对于 Python 2 是必需的,其中常规 open 函数不允许您指定 encoding
t
twasbrillig

我通过将 .encode("utf-8") 添加到 soup 来修复它。

这意味着 print(soup) 变为 print(soup.encode("utf-8"))


不要在脚本中硬编码环境(例如控制台)的字符编码,print Unicode directly instead
这只是打印 bytes 对象的 repr,如果有很多 UTF-8 编码的文本,它将打印成乱七八糟的 \x 序列。正如@JFSebastian 建议的那样,我建议使用 win_unicode_console
我使用了上述解决方案,但仍然遇到问题: class MyStreamListener(tweepy.StreamListener): def on_status(self, status): print(str(status.encode("utf-8"))) UnicodeEncodeError: 'charmap' codec can' t 在位置 87 编码字符 '\u2019':字符映射到
这使它打印出 b'\x02x\xc2\xa9' (一个字节对象)
print(soup.encode("utf-8")) 为我工作,但在此之前我还必须添加 with open("f_name", encoding="utf-8") as f: soup = BeautifulSoup(f, "html.parser")
M
MilkyWay90

在 Python 3.7 和运行 Windows 10 中,这是可行的(我不确定它是否可以在其他平台和/或其他版本的 Python 上运行)

替换此行:

with open('filename', 'w') as f:

有了这个:

with open('filename', 'w', encoding='utf-8') as f:

之所以能工作,是因为在使用文件的时候编码改成了 UTF-8,所以 UTF-8 中的字符可以转成文本,而不是遇到 UTF-8 字符时返回错误当前编码不支持。


打印(汤)返回 \xd0\xbf\xd0\xbe\xd0\xb6\xd0\xb0\xd0\xbb\xd1\x83\xd0\xb9\xd
@CoffeeinTime 看起来 UTF-16 错误地转换为某种 8 位编码,或者可能使用 Pyhon 2。您显示的字符串被截断,但它似乎以“뿐뻐뛐냐믐菑말”开头(我不读韩文所以我不知道这是否有意义)。演示:ideone.com/092Jnk
V
Voy
set PYTHONIOENCODING=utf-8
set PYTHONLEGACYWINDOWSSTDIO=utf-8

您可能需要也可能不需要设置第二个环境变量 PYTHONLEGACYWINDOWSSTDIO

或者,这可以在代码中完成(尽管似乎建议通过 env vars 来完成):

sys.stdin.reconfigure(encoding='utf-8')
sys.stdout.reconfigure(encoding='utf-8')

另外:重现这个错误有点痛苦,所以也把它留在这里,以防您需要在您的机器上重现它:

set PYTHONIOENCODING=windows-1252
set PYTHONLEGACYWINDOWSSTDIO=windows-1252

太棒了;我在 Windows 系统上使用 Python 调试器 (pdb) 查看使用 utf-8 并包含大量表情符号的源代码时遇到此错误。每次我执行“list”命令查看我在哪里时,都会出现“charmap”错误。设置这两个环境变量让我的调试如丝般顺滑。
sys.stdin.reconfigure 在 Python 3.9.0 上无效,它会抛出 AttributeError: 'StdInputFile' object has no attribute 'reconfigure'
在 Windows 10 上,使用 GIT BASH,设置上述环境变量不起作用,但是,在实际的 python 代码文件中设置两行 DID 工作:sys.stdin.reconfigure(encoding='utf-8') sys.stdout.reconfigure(encoding='utf-8')
@Suncatcher 尝试在不同的 IDE 中运行这个 Python 脚本
@PetrL。为什么我应该使用 IDE?所有有效的 Python 命令都应该在 Python Shell 中是可解释的,否则它们是无效的
S
Suraj Rao

在保存 get 请求的响应时,在窗口 10 上的 Python 3.7 上抛出了相同的错误。从 URL 接收到的响应,编码是 UTF-8,因此始终建议检查编码,以便可以传递相同的编码以避免此类微不足道的问题因为它真的在生产中浪费了很多时间

import requests
resp = requests.get('https://en.wikipedia.org/wiki/NIFTY_50')
print(resp.encoding)
with open ('NiftyList.txt', 'w') as f:
    f.write(resp.text)

当我使用 open 命令添加 encoding="utf-8" 时,它以正确的响应保存了文件

with open ('NiftyList.txt', 'w', encoding="utf-8") as f:
    f.write(resp.text)

P
Pardhu Gopalam

即使我在尝试打印、读/写或打开它时也遇到了同样的编码问题。正如上面提到的其他人所提到的,如果您尝试打印它,添加 .encoding="utf-8" 会有所帮助。

汤.编码(“utf-8”)

如果您尝试打开抓取的数据并将其写入文件,请使用 (......,encoding="utf-8") 打开文件

使用 open(filename_csv , 'w', newline='',encoding="utf-8") 作为 csv_file:


M
MilkyWay90

对于仍然收到此错误的用户,将 encode("utf-8") 添加到 soup 也将解决此问题。

soup = BeautifulSoup(html_doc, 'html.parser').encode("utf-8")
print(soup)

执行此操作后,soup 不再是 BeautifulSoup 对象,因此无法对其进行操作或搜索
t
tripleee

这个问题有多个方面。基本问题是您要输出到哪个字符集。您可能还必须弄清楚输入字符集。

打印(使用 printwrite)到具有显式 encoding="..." 的文件会将 Python 的内部 Unicode 表示转换为该编码。如果输出包含该编码不支持的字符,您将获得 UnicodeEncodeError。例如,您不能在编码为 "cp1252" 的文件中写入俄语、中文、印度语、希伯来语、阿拉伯语、表情符号或......除了一组 200 多个受限的西方字符之外的任何内容,因为这个受限的 8 位字符set 无法表示这些字符。

基本上任何 8 位字符集都会出现同样的问题,包括几乎所有的旧版 Windows 代码页(437、850、1250、1251 等),尽管其中一些支持一些额外的脚本,而不是英语(例如,1251 支持西里尔文,因此您可以编写俄语、乌克兰语、塞尔维亚语、保加利亚语等)。 8 位编码最多只有 256 个字符代码,无法表示不在其中的字符。

也许现在是阅读 Joel Spolsky 的The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)的好时机

在终端无法打印 Unicode 的平台上(现在只有 Windows,但如果您喜欢逆向计算,这个问题在上个千年的其他平台上也很普遍)尝试 print Unicode 字符串也可以产生这个错误,或输出 mojibake。如果您看到类似 Héllö 而不是 Héllö 的内容,这就是您的问题。

简而言之,那么,您需要知道:

您抓取的页面的字符集是什么,或者您收到的数据是什么?是否正确刮擦?发起者是否正确识别了其编码,或者您是否能够以其他方式获得此信息(或猜测)?一些网站错误地声明了与页面实际包含的字符集不同的字符集,一些网站错误地配置了 Web 服务器和后端数据库之间的连接。有关一些解决方案的更详细示例,请参见例如使用正确的字符编码(python 请求 + beautifulsoup)刮擦。

你想写什么字符集?如果打印到屏幕上,您的终端配置是否正确,您的 Python 解释器是否配置相同?或许也可以看看 How to display utf-8 in windows console

如果您在这里,这些问题之一的答案可能不是“UTF-8”。这也越来越成为网页的流行编码,尽管以前的标准是 ISO-8859-1(又名 Latin-1)和最近的 Windows 代码页 1252。

展望未来,除了一些边缘用例之外,您基本上希望所有文本数据都是 Unicode。通常,这意味着 UTF-8,尽管在 Windows 上(或者如果您需要 Java 兼容性),UTF-16 也是模糊可行的,尽管有些麻烦。 (还有其他几种 Unicode 序列化格式,在特殊情况下可能很有用。UTF-32 在技术上是微不足道的,但会占用更多内存;UTF-7 用于一些需要 7 位 ASCII 的网络协议运输。)也许另见https://utf8everywhere.org/

当然,如果您要打印到文件,您还需要使用可以正确显示该文件的工具来检查该文件。一个常见的飞行员错误是使用仅显示当前选择的系统编码的工具打开文件,或者尝试猜测编码但猜测错误的工具。同样,使用 Windows 代码页 1252 查看 UTF-8 文本时的常见症状会导致,例如,Héllö 显示为 Héllö

如果字符数据的编码未知,则没有简单的方法可以自动建立它。如果您知道文本应该代表什么,您也许可以推断出来,但这通常是一个手动过程,涉及一些猜测。 (像 chardetftfy 这样的自动工具可以提供帮助,但有时它们也会出错。)

要确定您正在查看的编码,如果您可以识别字符中未正确显示的各个字节,这将很有帮助。例如,如果您正在查看 H\x8ell\x9a 但希望它表示 Héllö,则可以在转换表中查找字节。我在 https://tripleee.github.io/8bit 发布了一张这样的表格,您可以在该示例中看到,它可能是旧版 Mac 8 位字符集之一;如果有更多数据点,也许您可以将其缩小到其中的一个(如果没有,它们中的任何一个都可以在实践中使用,因为您关心的所有代码点都映射到相同的 Unicode 字符)。

大多数平台上的 Python 3 默认所有输入和输出都使用 UTF-8,但在 Windows 上,通常情况并非如此。然后它将默认为系统的默认编码(在某些 Microsoft 文档中仍被误导性地称为“ANSI 代码页”),这取决于许多因素。在西方系统上,开箱即用的默认编码通常是 Windows 代码页 1252。(早期的 Python 版本有一些不同的期望,在 Python 2 中,内部字符串表示不是 Unicode。)

如果您在 Windows 上并将 UTF-8 写入文件,则可能指定 encoding="utf-8-sig" 以在文件开头添加 BOM 序列。严格来说,这不是必需的或正确的,但某些 Windows 工具需要它来正确识别编码。

这里的几个较早的答案建议盲目地应用一些编码,但希望这可以帮助您了解这通常不是正确的方法,以及如何确定要使用哪种编码。


K
Karim Sherif

如果您使用的是 windows 尝试传递 encoding='latin1', encoding='iso-8859-1' 或 encoding='cp1252' 示例:

csv_data = pd.read_csv(csvpath,encoding='iso-8859-1')
print(print(soup.encode('iso-8859-1')))

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅