【问题标题】:UnicodeEncodeError: 'latin-1' codec can't encode character u'\u2014'UnicodeEncodeError:“latin-1”编解码器无法编码字符 u'\u2014'
【发布时间】:2015-04-29 10:16:12
【问题描述】:

我收到此错误 UnicodeEncodeError: 'latin-1' codec can't encode character u'\u2014'

我正在尝试将大量新闻文章加载到 MySQLdb 中。但是我在处理非标准字符时遇到了困难,对于各种字符,我都会遇到数百个这样的错误。我可以使用 .replace() 单独处理它们,尽管我想要一个更完整的解决方案来正确处理它们。

ubuntu@ip-10-0-0-21:~/scripts/work$ python test_db_load_error.py
Traceback (most recent call last):
  File "test_db_load_error.py", line 27, in <module>
    cursor.execute(sql_load)
  File "/usr/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 157, in execute
    query = query.encode(charset)
UnicodeEncodeError: 'latin-1' codec can't encode character u'\u2014' in position 158: ordinal not in range(256)

我的脚本;

import MySQLdb as mdb
from goose import Goose
import string
import datetime

host = 'rds.amazonaws.com'
user = 'news'
password = 'xxxxxxx'
db_name = 'news_reader'
conn = mdb.connect(host, user, password, db_name)

url = 'http://www.dailymail.co.uk/wires/ap/article-3060183/Andrew-Lesnie-Lord-Rings-cinematographer-dies.html?ITO=1490&ns_mchannel=rss&ns_campaign=1490'
g = Goose()
article = g.extract(url=url)
body = article.cleaned_text
body = body.replace("'","`")
load_date = str(datetime.datetime.now())
summary = article.meta_description
title = article.title
image = article.top_image

sql_load = "insert into articles " \
        "    (title,summary,article,,image,source,load_date) " \
        "     values ('%s','%s','%s','%s','%s','%s');" % \
        (title,summary,body,image,url,load_date)
cursor = conn.cursor()
cursor.execute(sql_load)
#conn.commit()

任何帮助将不胜感激。

【问题讨论】:

  • 是否可以重新配置数据库以存储 UTF-8 而不是 Latin-1?这需要对现有数据进行重新编码(数据迁移)。
  • 你有什么样的数据库字符编码?你定义了它还是mysql的默认值?如果是你有 latin1 但也许你需要 utf-8 取决于你想要插入的内容
  • 你真的应该在这里使用 SQL 参数,而不是使用字符串插值。从sql_load 行中删除% (....) 并将元组移动到cursor.execute() 的第二个参数。 sql_load = ".... query string with %s placeholders ..."cursor.execute(sql_load, (title, summary, body, image, url, load_date)).
  • 谢谢,你说得对。我的应用程序仍在测试中,所以我只是删除了所有表并使用 charset=utf8 重新创建它们。现在一切正常。 :)
  • 我在尝试插入时突然遇到同样的错误。我怎样才能知道这是来自 MySQL 服务器还是来自 SQLAlchemy(默认情况下应该使用 utf-8,尤其是 Py3)?

标签: python mysql unicode


【解决方案1】:

当您创建 mysqldb 连接时,将 charset='utf8' 传递给连接。

conn = mdb.connect(host, user, password, db_name, charset='utf8')

【讨论】:

  • 前提是没有任何预先存在的数据。否则,您需要在迁移中重新编码该数据。
  • 看来SQLAlchemy默认设置了utf-8。但是,如何确保它设置为 utf-8,或者如何查询现有配置?
【解决方案2】:

如果您的数据库实际上是为 Latin-1 配置的,那么您不能在其中存储非 Latin-1 字符。其中包括U+2014, EM DASH

理想的解决方案是切换到为 UTF-8 配置的数据库。在最初创建数据库时传递charset='utf-8',每次连接到它时。 (如果您已经有现有数据,您可能希望使用 MySQL 工具将旧数据库迁移到新数据库,而不是 Python 代码,但基本思想是相同的。)

但是,有时这是不可能的。也许您有其他无法更新的软件,需要 Latin-1,并且需要共享同一个数据库。或者,您可能以无法通过编程方式混合的方式混合了 Latin-1 文本和二进制数据,或者您的数据库太大而无法迁移,或者其他什么。在这种情况下,您有两种选择:

  • 在存储和搜索之前破坏性地将您的字符串转换为 Latin-1。例如,您可能希望将破折号转换为 ---,或者这并不是那么重要,您可以将所有非拉丁 1 字符转换为 ?(这样更快且更简单)。

  • 想出一种编码方案,将非拉丁语 1 字符偷运到数据库中。这意味着某些搜索变得更加复杂,或者无法直接在数据库中完成。

【讨论】:

  • 如何了解数据库的配置方式?
【解决方案3】:

这可能是一个沉重的阅读,但至少让我开始了。

http://www.joelonsoftware.com/articles/Unicode.html

【讨论】:

  • 谢谢我现在得到这个错误; 'ascii' 编解码器无法编码字符 u'\u2019'。在我发布另一个问题之前,我会阅读您的文档并尝试自己弄清楚
猜你喜欢
  • 2018-07-07
  • 2011-04-25
  • 2013-04-21
  • 2015-04-13
  • 2011-04-05
  • 2014-12-22
  • 2016-09-10
相关资源
最近更新 更多