【问题标题】:UTF-8 encoding issue with Python 3 [duplicate]Python 3的UTF-8编码问题[重复]
【发布时间】:2017-03-02 22:25:25
【问题描述】:

上周我用 Python 写了a Wikipedia scraper

它会抓取法语页面,因此我必须管理 UTF-8 编码以避免错误。我在脚本开头用这些行做了这个:

#!/usr/bin/python
# -*- coding: utf-8 -*-

我也像这样对抓取的字符串进行编码:

adresse = monuments[1].get_text().encode('utf-8')

我的第一个脚本在 Python 2.7 上运行得非常好,但我为 Python 3 重写了它(尤其是使用 urllib.request),UTF-8 不再工作了。

我在抓取前几个元素后得到了这些错误:

File "scraper_monu_historiques_ge_py3.py", line 19, in <module>
    url = urllib.request.urlopen(url_ville).read() # et on ouvre chacune d'entre elles
File "/usr/lib/python3.4/urllib/request.py", line 153, in urlopen
    return opener.open(url, data, timeout)
File "/usr/lib/python3.4/urllib/request.py", line 455, in open
    response = self._open(req, data)
File "/usr/lib/python3.4/urllib/request.py", line 473, in _open
'_open', req)
File "/usr/lib/python3.4/urllib/request.py", line 433, in _call_chain
    result = func(*args)
File "/usr/lib/python3.4/urllib/request.py", line 1217, in https_open
    context=self._context, check_hostname=self._check_hostname)
File "/usr/lib/python3.4/urllib/request.py", line 1174, in do_open
h.request(req.get_method(), req.selector, req.data, headers)
File "/usr/lib/python3.4/http/client.py", line 1090, in request
self._send_request(method, url, body, headers)
File "/usr/lib/python3.4/http/client.py", line 1118, in _send_request
self.putrequest(method, url, **skips)
File "/usr/lib/python3.4/http/client.py", line 975, in putrequest
self._output(request.encode('ascii'))
UnicodeEncodeError: 'ascii' codec can't encode character '\xe9' in position 58: ordinal not in range(128)

我不明白为什么,因为它在 Python 2.7 中运行良好...我发布了 a version of this WIP on Github

【问题讨论】:

  • # -*- coding: utf-8 -*- 指令对脚本处理 Unicode 数据的方式没有影响,它只是告诉 Python 解释器脚本本身的文本编码。您可能会发现这篇文章很有帮助:Pragmatic Unicode,由 SO 资深人士 Ned Batchelder 撰写。
  • 此代码 monuments[1].get_text().encode('utf-8') 将 unicode 转换为 utf-8。我怀疑那是你当时想要的,但不可能知道,因为这里没有其他代码。你也没有说你在哪一行得到错误,也没有说那是变量的值。
  • 我的错!错误在第 19 行:url = urllib.request.urlopen(url_ville).read() 我认为这与列表分离有关,但在 Python 2.7 中运行良好...
  • Python 2 和 3 处理字符串及其编码的方式非常不同,因此它完全有可能在另一个上失败但在另一个上传递。
  • url_ville(或只是它的ville 部分)需要根据stackoverflow.com/questions/4389572/… 中接受的答案进行编码。

标签: python encoding utf-8 urllib


【解决方案1】:

您将包含非 ASCII 字符的字符串传递给 urllib.urlopen,这不是有效的 URI(不过,它是有效的 IRI 或国际资源标识符)。

在将 IRI 传递给 urlopen 之前,您需要将其设为有效的 URI。这件事的具体情况 取决于 IRI 的哪个部分包含非 ASCII 字符:域部分应使用 Punycode 编码,而路径应使用 percent-encoding

由于您的问题完全是由于路径包含 Unicode 字符,假设您的 IRI 存储在变量 iri 中,您可以使用以下方法修复它:

import urllib.parse
import urllib.request

split_url = list(urllib.parse.urlsplit(iri))
split_url[2] = urllib.parse.quote(split_url[2])    # the third component is the path of the URL/IRI
url = urllib.parse.urlunsplit(split_url)

urllib.request.urlopen(url).read()

但是,如果您可以避免使用 urllib 并可以选择使用 requests 库,我建议您这样做。该库更易于使用并具有自动 IRI 处理功能。

【讨论】:

  • 或者简而言之:url_ville = depart + quote(ville).
  • 是的。我不愿意参考他的实际代码,因为它不包含在问题中。
  • 我刚刚用请求测试了另一个版本的脚本(我更喜欢更短的代码),它运行良好!非常感谢你:-)!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-18
  • 1970-01-01
  • 2010-12-01
  • 1970-01-01
相关资源
最近更新 更多