UnicodeEncodeError: 'latin-1' 编码无法编码字符 u'\u2014'

3

我遇到了这个错误:UnicodeEncodeError: 'latin-1'编解码器无法编码字符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是一个选项吗?这将需要对现有数据进行重新编码(数据迁移)。 - Martijn Pieters
你们使用的是什么类型的数据库字符编码?是自定义的还是MySQL默认的?如果你们使用的是latin1,但是根据你们要插入的内容,可能需要使用utf-8。 - Ricardo Burillo
你应该在这里使用SQL参数,而不是使用字符串插值。从sql_load行中删除% (....),并将元组移动到cursor.execute()的第二个参数中。 sql_load =“....带有%s占位符的查询字符串...”cursor.execute(sql_load,(title,summary,body,image,url,load_date)) - Martijn Pieters
谢谢,你们都是正确的。我的应用程序仍在测试中,所以我只是删除了所有表格并使用charset=utf8重新创建它们。现在一切正常。 :) - Rhys
当我尝试插入时,突然出现了相同的错误。我该如何确定这是来自MySQL服务器还是SQLAlchemy(默认情况下应使用utf-8,特别是在Py3中)? - Jens
3个回答

7
当您创建mysqldb连接时,请在连接中传递charset='utf8'
conn = mdb.connect(host, user, password, db_name, charset='utf8')

1
只要没有预先存在的数据,否则您需要在迁移中重新编码该数据。 - Martijn Pieters
似乎SQLAlchemy默认设置为utf-8。然而,我该如何确保它被设置为utf-8,或者如何查询现有的配置是否为utf-8? - Jens

2
如果您的数据库实际上配置为Latin-1,则无法在其中存储非Latin-1字符,包括U+2014,EM DASH
最理想的解决方案是切换到配置为UTF-8的数据库。在最初创建数据库时和每次连接到数据库时,只需传递charset='utf-8'即可。(如果您已经有现有数据,则可能需要使用MySQL工具将旧数据库迁移到新数据库,而不是Python代码,但基本思路相同。)
然而,有时这是不可能的。也许您有其他无法更新、需要Latin-1且需要共享同一数据库的软件。或者您已经混合使用了Latin-1文本和二进制数据,无法通过编程方式分离,或者您的数据库太大而无法迁移等。在这种情况下,您有两个选择:
  • 在存储和搜索之前将字符串破坏性地转换为 Latin-1。例如,您可能想将 em 破折号转换为---,或者可能并不那么重要,您可以将所有非 Latin-1 字符转换为?(这更快且更简单)。

  • 想出一个编码方案来将非 Latin-1 字符走私到数据库中。这意味着某些搜索变得更加复杂,或者根本无法直接在数据库中完成。


我该如何找出数据库是如何配置的? - Jens

0

谢谢,我现在遇到了这个错误:'ascii'编解码器无法编码字符u'\u2019'。在我发另一个问题之前,我会阅读您的文档并尝试自己解决它。 - Rhys

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接