【问题标题】:'ascii' codec can't encode character : ordinal not in range (128)“ascii”编解码器无法编码字符:序数不在范围内(128)
【发布时间】:2019-09-29 22:38:51
【问题描述】:

我正在使用 selenium 和 beautifulsoup 抓取一些网页。我正在遍历一堆链接,获取信息,然后将其转储到 JSON 中:

for event in events:

    case = {'Artist': item['Artist'], 'Date': item['Date'], 'Time': item['Time'], 'Venue': item['Venue'],
        'Address': item['Address'], 'Coordinates': item['Coordinates']}
    item[event] = case

with open("testScrape.json", "w") as writeJSON:
json.dump(item, writeJSON, ensure_ascii=False)

当我访问此链接时:https://www.bandsintown.com/e/100778334-jean-deaux-music-at-rickshaw-stop?came_from=257&utm_medium=web&utm_source=home&utm_campaign=event

代码中断,我收到以下错误:

 Traceback (most recent call last):
  File "/Users/s/PycharmProjects/hi/BandsintownWebScraper.py", line 126, in <module>
    json.dump(item, writeJSON, ensure_ascii=False)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 190, in dump
    fp.write(chunk)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe6' in position 7: ordinal not in range(128)

我试过用:

json.dump(item, writeJSON, ensure_ascii=False).decode('utf-8')

还有:

json.dump(item, writeJSON, ensure_ascii=False).encode('utf-8')

没有成功。我相信这是导致此失败的链接上的 ï 字符。谁能简要介绍一下正在发生的事情、编码/解码的含义以及如何解决这个问题?提前致谢。

【问题讨论】:

  • 这个错误可能意味着数据不是UTF-8,而是其他编码——即Latin1CP1250
  • Python 将文本保存为 unicode - 这意味着每个字符甚至可以使用 8 个字节。为了发送或保存在文件中,它被转换(编码)为utf-8latin1 等以使用更少的空间。编码字符可能使用 1 个字节,其他 2 个或更多字节 - 并且它使用更少的空间然后 8 个字节用于每个字符。当你得到它时,你必须将它转换(解码)回 unicode,以便 Python 可以使用它。
  • 您没有显示完整的错误(Traceback),但我认为问题不在于这部分代码,而在于从网页获取数据的代码。也许您可能必须从页面解码数据。或者您可能需要在open(..., encode='utf-8') 中设置编码

标签: python json selenium utf-8 beautifulsoup


【解决方案1】:

在 shell 中运行 python 脚本之前,您可能需要设置 PYTHONIOENCODING。 例如,我在将 python 脚本输出重定向到日志文件时遇到了同样的错误:

$ your_python_script > output.log
'ascii' codec can't encode characters in position xxxxx-xxxxx: ordinal not in range(128)

在 shell 中将 PYTHONIOENCODING 更改为 UTF8 后,脚本执行时没有 ASCII 编解码器错误:

$ export PYTHONIOENCODING=utf8

$ your_python_script > output.log

【讨论】:

    【解决方案2】:

    您的问题是,在 Python 2 中,file 对象(由open() 返回)只能写入str 对象,而不是unicode 对象。将ensure_ascii=False 传递给json.dump() 使其尝试将Unicode 字符串作为unicode 对象直接写入文件,这将失败。

    json.dump(item, writeJSON, ensure_ascii=False).encode('utf-8')
    

    这个尝试的修复不起作用,因为json.dump() 没有返回任何东西;相反,它将内容直接写入文件。 (如果 item 中没有任何 Unicode 文本,这将在 json.dump() 完成后崩溃——json.dump() 返回 None,它不能调用 .encode()。)

    有三种方法可以解决这个问题:

    1. 使用 Python 3。strunicode 在 Python 3 中的统一使您现有的代码可以按原样工作;无需更改代码。

    2. 从您对 json.dump 的呼叫中删除 ensure_ascii=False。非 ASCII 字符将以转义形式写入文件 - 例如,ï 将写入 \u00ef。这是表示 Unicode 字符的一种完全有效的方式,大多数 JSON 库都能很好地处理它。

    3. file 对象包装在UTF-8 StreamWriter 中:

      import codecs
      with codecs.getwriter("utf8")(open("testScrape.json", "w")) as writeJSON:
          json.dump(item, writeJSON, ensure_ascii=False)
      

    【讨论】:

    • 一种与修复 1 和 3 同时做同样事情的方法是使用 io.open 而不是 Python 2 的内置 open 函数。 io.open 和 Python 3 的 open 一样,所以默认支持 Unicode。
    • @Blckknght,你应该这样回答,它肯定对我有帮助:)
    【解决方案3】:

    pip install unidecode

    从单解码导入单解码

    <!-- language: python -->
    for col in ['column1', 'column2']:
        df[col] = df[col].apply(unidecode)
    <!-- end snippet -->
    

    如果这是一个 pandas 对象,那么只需将列的名称放在 [] 中,将其作为列表传递.. 因为我今天遇到了同样的问题,并想通了。

    【讨论】:

      猜你喜欢
      • 2011-01-31
      • 1970-01-01
      • 2019-07-13
      • 2019-11-10
      • 2021-05-14
      • 2023-03-03
      • 1970-01-01
      • 2014-01-22
      • 2012-06-11
      相关资源
      最近更新 更多