代码之家  ›  专栏  ›  技术社区  ›  rolisz

用Python解码UTF-8 URL

  •  0
  • rolisz  · 技术社区  · 12 年前

    我有一个类似“pe%20to%C5%A3i%20mai”的字符串。当我将urlib.parse.unquot应用于它时,我得到“pe to \u0163i-mai”。如果我试着把它写到一个文件中,我会得到那些精确的simbol,而不是预期的字形。

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

    编辑:我使用的是Python 3.2

    编辑2:所以我发现 urllib.parse.unquote 工作正常,而我的问题实际上是我正在用 yaml.dump 这似乎把事情搞砸了。为什么?

    4 回复  |  直到 12 年前
        1
  •  4
  •   jfs    12 年前

    使现代化 :如果输出文件是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转义。


    url是正确的。你不需要对它做任何事情:

    #!/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 ţţţ
    
        2
  •  2
  •   Maria Zverina    12 年前

    尝试 decode 使用 unicode_escape

    例如:

    >>> print "pe to\u0163i mai".decode('unicode_escape')
    pe toţi mai
    
        3
  •  2
  •   Mark Byers    12 年前

    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
    

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

        4
  •  1
  •   rolisz    12 年前

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

    我的解决方案是:

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

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