如何使用 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 =]
我有点菜鸟。所以我试图解析 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
是 á
.
您可以通过获取字符串长度来仔细检查——á
应该是 1(字符)或 2(字节),但显然 \xc3\xa1
.[=16 是 8 =]