【问题标题】:Can't open Unicode URL with Python无法使用 Python 打开 Unicode URL
【发布时间】:2010-12-27 08:44:56
【问题描述】:

使用 Python 2.5.2 和 Linux Debian,我正在尝试从包含西班牙语字符 'í' 的西班牙语 URL 获取内容:

import urllib
url = u'http://mydomain.es/índice.html'
content = urllib.urlopen(url).read()

我收到此错误:

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

在将 url 传递给 urllib 之前,我尝试过使用:

url = urllib.quote(url)

还有这个:

url = url.encode('UTF-8')

但他们没有工作。

你能告诉我我做错了什么吗?

【问题讨论】:

    标签: python unicode


    【解决方案1】:

    将 URL 编码为 utf-8,应该可以。我想知道您的源文件是否正确编码,以及解释器是否知道它。例如,如果你的 python 源文件保存为 UTF-8,那么你应该有

    # coding=UTF-8
    

    作为第一行或第二行。

    import urllib
    url = u'http://mydomain.es/índice.html'
    content = urllib.urlopen(url.encode('utf-8')).read()
    

    为我工作。

    编辑:另外,请注意交互式 Python 会话(无论是通过 IDLE 还是控制台)中的 Unicode 文本充满了与编码相关的困难。在这些情况下,您应该使用 Unicode 文字(例如您的情况下的 \u00ED)。

    【讨论】:

      【解决方案2】:

      这对我有用:

      #!/usr/bin/env python
      # define source file encoding, see: http://www.python.org/dev/peps/pep-0263/
      # -*- coding: utf-8 -*-
      
      import urllib
      url = u'http://example.com/índice.html'
      content = urllib.urlopen(url.encode("UTF-8")).read()
      

      【讨论】:

        【解决方案3】:

        根据适用标准RFC 1378,URL 只能包含 ASCII 字符。很好的解释here,我引用:

        "...只有字母数字 [0-9a-zA-Z], 特殊字符 "$-_.+!*'()," [不包括引号 - ed],和 用于他们的保留字符 可使用保留用途 在 URL 中未编码。”

        正如我给出的 URL 所解释的,这可能意味着您必须将“带有尖音的小写 i”替换为 `%ED'。

        【讨论】:

        • 我相信这已经改变了,至少域现在可以包含任意 Unicode 字符。
        • @Cerin 有点像。 IRIs can contain arbitrary Unicode characters,但是当您将它们转换为常规 URI 时,它们会使用“Punycode”(用于域组件)和百分比编码(用于路径组件)标准化为 ASCII。
        【解决方案4】:

        它对我有用。确保您使用的是相当新的 Python 版本,并且您的文件编码是正确的。 这是我的代码:

        # -*- coding: utf-8 -*-
        import urllib
        url = u'http://mydomain.es/índice.html'
        url = url.encode('utf-8')
        content = urllib.urlopen(url).read()
        

        (mydomain.es 不存在,因此 DNS 查找失败,但此时没有 unicode 问题。)

        【讨论】:

        • 使用 python 3 我在使用此代码时得到AttributeError: 'bytes' object has no attribute 'timeout'。有没有 python 3 的解决方案?
        • @BrandonIbbotson 您应该尝试:urllib.parse.quote(url) 而不是 url.encode('utf-8') 您可以在此处阅读更多信息:docs.python.org/dev/library/…
        【解决方案5】:

        我现在也有类似的情况。我正在尝试下载图像。我在 JSON 文件中从服务器检索 URL。一些图像包含非 ASCII 字符。这会引发错误:

        for image in product["images"]: 
            filename = os.path.basename(image) 
            filepath = product_path + "/" + filename 
            urllib.request.urlretrieve(image, filepath) # error!
        

        UnicodeEncodeError: 'ascii' 编解码器无法在位置编码字符 '\xc7' ...


        我尝试过使用.encode("UTF-8"),但不能说它有帮助:

        # coding=UTF-8
        import urllib
        url = u"http://example.com/wp-content/uploads/2018/09/İMAGE-1.png"
        url = url.encode("UTF-8")
        urllib.request.urlretrieve(url, "D:\image-1.jpg")
        

        这只会引发另一个错误:

        TypeError: 不能在类似字节的对象上使用字符串模式


        然后我给了urllib.parse.quote(url)一个机会:

        import urllib
        url = "http://example.com/wp-content/uploads/2018/09/İMAGE-1.png"
        url = urllib.parse.quote(url)
        urllib.request.urlretrieve(url, "D:\image-1.jpg")
        

        这又引发了另一个错误:

        ValueError:未知 url 类型:'http%3A//example.com/wp-content/uploads/2018/09/%C4%B0MAGE-1.png'

        "http://..." 中的: 也被转义了,我认为这就是问题的原因。

        所以,我想出了一个解决方法。我只是引用/转义路径,而不是整个 URL。

        import urllib.request
        import urllib.parse
        url = "http://example.com/wp-content/uploads/2018/09/İMAGE-1.png"
        url = urllib.parse.urlparse(url)
        url = url.scheme + "://" + url.netloc + urllib.parse.quote(url.path)
        urllib.request.urlretrieve(url, "D:\image-1.jpg")
        

        这就是 URL 的样子:"http://example.com/wp-content/uploads/2018/09/%C4%B0MAGE-1.png",现在我可以下载图片了。

        【讨论】:

          猜你喜欢
          • 2021-09-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-25
          • 2019-02-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多