如何使用Python解码这个utf-8字符串,它是在一个随机的网站上挑选出来的,由Django ORM保存的?

2024-10-02 20:36:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我分析了一个文件,并使用Django将其内容保存在数据库中。网站是100%的英文版,所以我天真地以为它一直都是ASCII码,并很高兴地将文本保存为unicode码。

你猜故事的其余部分:-)

打印时,会出现常见的编码错误:

UnicodeEncodeError: 'ascii' codec can't encode character u'\u2019' in position 48: ordinal not in range(128)

快速搜索告诉我u'\u2019'是的UTF-8表示。

repr(string)显示:

"u'his son\\u2019s friend'"

当然,我尝试了django.utils.encoding.smart_str和使用string.encode('utf-8')的更直接的方法,最后得到了一些可打印的东西。不幸的是,它在my(LinuxUTF-8)终端中打印如下:

In [76]: repr(string.encode('utf-8'))
Out[76]: "'his son\\xe2\\x80\\x99s friend '"

In [77]: print string.encode('utf-8')
his son�s friend

不是我想的那样。我怀疑我对某些东西进行了双重编码,或者遗漏了重要的一点。

当然,文件的原始编码不会与文件混淆。我想我可以阅读HTTP头或者询问网站管理员,但是由于2019s看起来像UTF-8,所以我假设它是UTF-8。如果我错了,告诉我。

解决方案显然是值得赞赏的,但对原因以及如何避免这种情况再次发生的深刻解释将更为重要。我经常被编码所困扰,这说明我还没有完全掌握这门学科。


Tags: 文件djangoinfriend编码string网站utf
3条回答

你很好。你有正确的数据。是的,原始数据是UTF-8(基于上下文u2019,作为“s on”和“s”之间的撇号是完全有意义的)。奇怪的?错误字符可能只是意味着您的终端配置的字体没有此字符的标志符号(花式撇号)。没什么大不了的。数据在计算的地方是正确的。如果您感到紧张,可以尝试一些不同的终端/操作系统组合(我在使用iTerm的OS X上)。我花了很多时间向我的QA人员解释,可怕的问号字符只意味着他们的windows框上没有安装中文字体(在我的例子中,我们是用中文数据测试的)。以下是一些评论

#Create a Python Unicode object
#(abstract code points, independent of any encoding)
#single backslash tells python we want to represent
#a code point by its unicode code point number, typed out with ASCII numbers
>>> s1 = u'his son\u2019s friend'

#If you just type it at the prompt,
#the interpreter does the equivalent of `print repr(s1)`
#and since repr means "show it like a string typed into a python source file",
#you get your ASCII escaped version back
>>> s1
u'his son\u2019s friend'
>>> print repr(s1)
u'his son\u2019s friend'

#This isn't ASCII, so encoding into ASCII generates your original
#error as expected
>>> s1.encode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character
 u'\u2019' in position 7: 
ordinal not in range(128)

# Encode in UTF-8 and now we have a string,
# which gets displayed as hex escapes.     
#Unicode code point 2019 looks like it gets 3 bytes in UTF-8 (yup, it does)
>>> s1.encode('utf-8')
'his son\xe2\x80\x99s friend'

#My terminal DOES have a different glyph (symbol) to use here,
#so it displays OK for me.
#Note that my terminal has a different glyph for a normal ASCII apostrophe
#(straight vertical)
>>> print s1
his son’s friend
>>> repr(s1)
"u'his son\\u2019s friend'"
>>> str(s1.encode('utf-8'))
'his son\xe2\x80\x99s friend'

另请参见:http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html

另请参阅字符2019(e28099,十六进制,在此页上搜索“2019”:http://www.utf8-chartable.de/unicode-utf8-table.pl?start=8000

另请参见:http://www.joelonsoftware.com/articles/Unicode.html

也许我太天真了,但是。。。您的问题不只是转义了unicode代码点的前导\吗?

原始字符串的行为如下:

>>> s = u'his son\\u2019s friend'
>>> print(s)
his son\u2019s friend

但是删除转义\会得到:

>>> s = u'his son\u2019s friend'
>>> print(s)
his son’s friend

尝试调用如下python shell:

python2 -S -i -c 'import sys;sys.setdefaultencoding("utf-8");import site'

然后:

>>> s = u'his son\u2019s friend'
>>> print s.encode("utf-8")
his son’s friend

那么默认的编码是utf-8,它应该打印得很好。

相关问题 更多 >