在Python中解码UTF-8 URL

时间:2012-08-13 17:28:11

标签: python utf-8 python-3.x yaml urldecode

我有一个字符串,如“pe%20to%C5%A3i%20mai”。当我将urllib.parse.unquote应用于它时,我得到“pe to \ u016​​3i mai”。如果我尝试将其写入文件,我会得到那些精确的符号,而不是预期的字形。

如何将字符串转换为utf-8,以便在文件中使用正确的字形?

编辑:我正在使用Python 3.2

Edit2:所以我发现urllib.parse.unquote工作正常,我的问题实际上是我用yaml.dump序列化为YAML,这似乎搞砸了。为什么呢?

4 个答案:

答案 0 :(得分:4)

更新:如果输出文件是yaml文档,则可以忽略其中的\u0163。 Unicode转义在yaml文档中有效。

#!/usr/bin/env python3
import json

# json produces a subset of yaml
print(json.dumps('pe toţi mai')) # -> "pe to\u0163i mai"
print(json.dumps('pe toţi mai', ensure_ascii=False)) # -> "pe toţi mai"

注意:在最后一种情况下没有\u。两行代表相同的Python字符串。

yaml.dump()有类似的选项:allow_unicode。将其设置为True以避免Unicode转义。


网址是正确的。你不需要做任何事情:

#!/usr/bin/env python3
from urllib.parse import unquote

url =  "pe%20to%C5%A3i%20mai"
text = unquote(url)

with open('some_file', 'w', encoding='utf-8') as file:
    def p(line):
        print(line, file=file) # write line to file

    p(text)                # -> pe toţi mai
    p(repr(text))          # -> 'pe toţi mai'
    p(ascii(text))         # -> 'pe to\u0163i mai'

    p("pe to\u0163i mai")  # -> pe toţi mai
    p(r"pe to\u0163i mai") # -> pe to\u0163i mai
    #NOTE: r'' prefix

\u0163序列可能由字符编码错误处理程序引入:

with open('some_other_file', 'wb') as file: # write bytes
    file.write(text.encode('ascii', 'backslashreplace')) # -> pe to\u0163i mai

或者:

with open('another', 'w', encoding='ascii', errors='backslashreplace') as file:
    file.write(text) # -> pe to\u0163i mai

更多例子:

# introduce some more \u escapes
b = r"pe to\u0163i mai ţţţ".encode('ascii', 'backslashreplace') # bytes
print(b.decode('ascii')) # -> pe to\u0163i mai \u0163\u0163\u0163
# remove unicode escapes
print(b.decode('unicode-escape')) # -> pe toţi mai ţţţ

答案 1 :(得分:2)

Python 3

调用urllib.parse.unquote已经返回一个Unicode字符串:

>>> urllib.parse.unquote("pe%20to%C5%A3i%20mai")
'pe toţi mai'

如果没有得到该结果,则代码中必定是错误。请发布您的代码。

Python 2

使用decode从字节字符串中获取Unicode字符串:

>>> import urllib2
>>> print urllib2.unquote("pe%20to%C5%A3i%20mai").decode('utf-8')
pe toţi mai

请记住,当您将Unicode字符串写入文件时,您必须再次对其进行编码。您可以选择以UTF-8的形式写入文件,但如果您愿意,也可以选择不同的编码。您还必须记住在从文件读回时使用相同的编码。您可能会发现codecs模块在​​读取和写入文件时用于指定编码。

>>> import urllib2, codecs
>>> s = urllib2.unquote("pe%20to%C5%A3i%20mai").decode('utf-8')

>>> # Write the string to a file.
>>> with codecs.open('test.txt', 'w', 'utf-8') as f:
...     f.write(s)

>>> # Read the string back from the file.
>>> with codecs.open('test.txt', 'r', 'utf-8') as f:
...     s2 = f.read()

一个可能令人困惑的问题是,在交互式解释器中,Unicode字符串有时使用\uxxxx表示法而不是实际字符显示:

>>> s
u'pe to\u0163i mai'
>>> print s
pe toţi mai

这并不意味着字符串是“错误的”。这就是翻译工作的方式。

答案 2 :(得分:2)

使用decode尝试unicode_escape

E.g:

>>> print "pe to\u0163i mai".decode('unicode_escape')
pe toţi mai

答案 3 :(得分:1)

urllib.parse.unquote返回了正确的UTF-8字符串,并将其直接写入返回的文件中,达到了预期的结果。问题出在yaml上。默认情况下,它不使用UTF-8编码。

我的解决方案是:

yaml.dump("pe%20to%C5%A3i%20mai",encoding="utf-8").decode("unicode-escape")

感谢J.F. Sebastian和Mark Byers问我正确的问题,这些问题帮助我解决了这个问题!