首页 > 解决方案 > 内置解码方法的异常行为(也使用了 aiohttp)

问题描述

所以我试图刮掉整个页面。我希望两者都能正常工作。所以这是不起作用的代码:

import aiohttp
import asyncio

url = "https://unsplash.com/s/photos/dogs"

async def main():
    async with aiohttp.ClientSession() as s:
        async with s.get(url) as r:
            enc = str(r.get_encoding())
            bytes = await r.read() <--- returns <class 'bytes'>
            with open("stuff.html", "w") as f:
                f.write(bytes.decode(encoding=enc, errors="ignore")) <-- in errors I've tried all possible accepted values.

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

这导致UnicodeEncodeError: 'charmap' codec can't encode character '\u2713' in position 58100: character maps to <undefined>. 我假设是在指定位置的一个字符,由于某种原因无法解码并转换为字符串。通过将main函数修改为以下内容,它可以正常工作。

async def main():
    async with aiohttp.ClientSession() as s:
        async with s.get(url) as r:
            enc = str(r.get_encoding())
            bytes = await r.read()
        with open("stuf.html", "wb") as f:
            f.write(bytes)

我不确定为什么它不起作用。因为在第二个代码块中,我只是将字节写入stuff.html使用上下文管理器调用的文件中。并在第一个代码块中。我只是用更长的方法来做同样的事情decode(),很好地解码它并将其转换为要写入文件的字符串。所以我不需要用wborw等​​打开文件。

标签: pythonpython-3.xencodingaiohttppython-3.9

解决方案


f.write(string)open()如果在调用中未设置显式编码,则在实际写入之前使用系统默认编码将字符串编码为字节。

在 Windows 上,文件系统编码是charmap默认的(参见locale.getpreferredencoding());不是utf-8。Charmap 无法编码所有 utf-8 字符,这就是您看到错误的原因。

有关于将 Windows 默认编码切换为 utf-8 的讨论,但该切换增加了向后兼容性问题,因此尚未执行。

当前文件编码状态在Python Docs for Windows中描述。


推荐阅读