【问题标题】:Unicode String in urllib.request [duplicate]urllib.request 中的 Unicode 字符串 [重复]
【发布时间】:2016-07-23 14:01:43
【问题描述】:

简短版本:我有一个变量s = 'bär'。我需要将s 转换为 ASCII 以便s = 'b%C3%A4r'

长版:

我正在使用urllib.request.urlopen() 从 URL 读取 mp3 发音文件。这工作得很好,除了我遇到了一个问题,因为 URL 通常包含 unicode 字符。例如,德语“Bär”。完整的 URL 是 https://d7mj4aqfscim2.cloudfront.net/tts/de/token/bär。实际上,将其作为 URL 输入 Chrome 是可行的,并且可以毫无问题地将我导航到 mp3 文件。但是,将相同的 URL 提供给 urllib 会产生问题。

我确定这是一个 unicode 问题,因为堆栈跟踪显示:

Traceback (most recent call last):
  File "importer.py", line 145, in <module>
    download_file(tuple[1], tuple[0], ".mp3")
  File "importer.py", line 81, in download_file
    with urllib.request.urlopen(url) as in_stream, open(to_fname+ext, 'wb') as out_file: #`with object as name:` safely __enter__() and __exit__() the runtime of object. `as` assigns `name` as referring to the object `object`.
  File "C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 162, in urlopen
    return opener.open(url, data, timeout)
  File "C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 465, in open
    response = self._open(req, data)
  File "C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 483, in _open
    '_open', req)
  File "C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 443, in _call_chain
    result = func(*args)
  File "C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 1283, in https_open
    context=self._context, check_hostname=self._check_hostname)
  File "C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 1240, in do_open
    h.request(req.get_method(), req.selector, req.data, headers)
  File "C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\http\client.py", line 1083, in request
    self._send_request(method, url, body, headers)
  File "C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\http\client.py", line 1118, in _send_request
    self.putrequest(method, url, **skips)
  File "C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\http\client.py", line 960, in putrequest
    self._output(request.encode('ascii'))
UnicodeEncodeError: 'ascii' codec can't encode character '\xfc' in position 19: ordinal not in range(128)

...除了明显的UnicodeEncodeError,我可以看到它正在尝试将encode() 转换为ASCII。

有趣的是,当我从 Chrome 复制 URL(而不是简单地将其输入到 Python 解释器中)时,它会将 bär 转换为 b%C3%A4r。当我将它提供给urllib.request.urlopen() 时,它处理得很好,因为所有这些字符都是 ASCII。所以我的目标是在我的程序中进行这种转换。我试图让我的原始字符串与 unicode 等效,但 unicodedata.normalize() 在其所有变体中都不起作用;此外,我不确定如何将 Unicode 存储为 ASCII,因为 Python 3 将所有字符串都存储为 Unicode,因此不会尝试转换文本。

【问题讨论】:

    标签: python python-3.x unicode encoding


    【解决方案1】:

    使用urllib.parse.quote:

    >>> urllib.parse.quote('bär')
    'b%C3%A4r'
    

    >>> urllib.parse.urljoin('https://d7mj4aqfscim2.cloudfront.net/tts/de/token/',
    ...                      urllib.parse.quote('bär'))
    'https://d7mj4aqfscim2.cloudfront.net/tts/de/token/b%C3%A4r'
    

    【讨论】:

    • 简单连接字符串和使用urljoin()有区别吗?另外,这种类型的 Unicode 有名称吗?鉴于我从normalize() 得到的 Unicode 完全不同,我想知道在讨论时如何命名它们。
    • 对于您的情况,不严格要求使用urljoin。但考虑一下:urllib.parse.urljoin('http://example.com/a/b/c', '/x/y/z')
    • 这不是 unicode。我听说它叫Percent encoding
    • 我试过了,它删除了/a/b/c 部分。但是将 /x/y/z 更改为 x/y/z 会使生成的 url 与 emaple.com/a/b/x/y/z 不同。我真的不知道 URL 的哪一部分将被保留/替换。
    • @AlexG,考虑一些文档('example.com/a/b')中的链接('a.html','/other/place.html')。 urljoin 对于获取这些链接的绝对 URL 很有用。
    猜你喜欢
    • 2017-05-21
    • 2015-03-25
    • 1970-01-01
    • 2012-05-03
    • 1970-01-01
    • 2013-05-27
    • 2020-02-14
    • 2017-07-26
    相关资源
    最近更新 更多