如何使用 Python 避免 MySQL 中的 b' 和 UTF-8 文字 3

How to avoid b' and UTF-8 literals in MySQL using Python 3

我有点菜鸟。所以我试图解析 html 页面并将内容放在 MySQL 中的一列中,但是我似乎无法让实际的外来字符出现,例如代替 á 我得到 xc3xa1 .我的 table 将 utf8mb4 作为其字符集和排序规则 utf8mb4_unicode_ci。我有以下设置:

Database_cnx = pymysql.connect(user='XXXX', password='XXXX',
                              host='XXXX',
                              database='XXXX',
                              use_unicode=True,
                              charset='utf8mb4')

article_content = str(row[3].encode("utf-8")).replace("'", "\'").replace("\"", "\'")

q_i = ("INSERT INTO article_items (" + ", ".join(article_table_col_name_new) + ")"
"VALUES ({:d}, \"{:s}\", \"{:s}\", \"{:s}\", \"{:s}\", \"{:s}\", \"{:s}\")".format(row[0], urlparse(row[1]).netloc, row[1], row[2].replace("\"", "'"), article_content, datetime.fromtimestamp(row[4]).strftime("%Y-%m-%d"), updated)
)

所以我怎么能在我的专栏中只显示实际的文章内容,而不是 b' 字节和 utf-8 文字。谢谢

问题是您将字符串显式编码为 UTF-8 字节,然后将该 UTF-8 字节转换为其字符串表示形式。

这就是这段代码的意思:

str(row[3].encode("utf-8"))

如果你不想那样做,就别那样做:

row[3]

这是一个展示您正在做的事情的例子:

>>> s = 'à'
>>> s
'à'
>>> s.encode('utf-8')
b'\xc3\xa0'
>>> str(s.encode('utf-8'))
"b'\xc3\xa0'"

你要的是第一个

更一般地说,在 bytes 上调用 str 几乎没有用。如果你不可避免地有一个 bytes 而你需要一个 str,你可以通过调用 decode 方法来获得它。但在这种情况下,您不可避免地会遇到 bytes。 (我的意思是,你 可以 row[3].encode("utf-8").decode("utf-8"),但那显然很傻。)


作为旁注——但非常重要的一点——你不应该试图将你的值 str.format 放入 SQL 字符串中。只需使用查询参数。 Here's the obligatory xkcd link 解释了 security/safety 问题,最重要的是,您使代码变得更加复杂,甚至效率更低。

换句话说,不是这样做:

"VALUES ({:d}, \"{:s}\", \"{:s}\", \"{:s}\", \"{:s}\", \"{:s}\", \"{:s}\")".format(row[0], urlparse(row[1]).netloc, row[1], row[2].replace("\"", "'"), article_content, datetime.fromtimestamp(row[4]).strftime("%Y-%m-%d"), updated)

…就这样做:

"VALUES (%s, %s, %s, %s, %s, %s, %s)"

然后,当您稍后执行查询时,将参数作为参数传递给 execute,而无需所有复杂的转换为字符串以及引用和替换嵌入的引号,只需按原样传递值。

db.execute(q_i, (
    row[0], urlparse(row[i]).netloc, row[1], row[2], article_content, 
    datetime.fromtimestamp(row[4]).strftime("%Y-%m-%d"), updated))

事实上,如果您的倒数第二列是(或可能是)DATETIME 列而不是 CHAR/VARCHAR/TEXT/任何其他列,你甚至不需要 strftime;只需传递 datetime 对象。

请注意,这意味着您根本不需要对 article_content 执行任何操作。引用的东西既不是必需的也不是一个好主意(除非你有其他一些特定于应用程序的原因需要避免文章中的 " 个字符),并且编码的东西没有解决任何问题,而只会导致新的。

instead of á I get xc3xa1

这表示问题出在将数据插入数据库时​​。回到那个代码,我们来讨论一下。

(可能是 \xc3\xa1,但反斜杠在某处丢失了。)C3A1á.

的 UTF-8 编码的十六进制

您可以通过获取字符串长度来仔细检查——á 应该是 1(字符)或 2(字节),但显然 \xc3\xa1.[=16 是 8 =]