7

我的背景是 Perl,但我正在尝试使用 Python 和 BeautifulSoup 来开发一个新项目。

在此示例中,我试图提取和呈现单个页面中包含的链接目标和链接文本。这是来源:

table_row = u'<tr><td>{}</td><td>{}</td></tr>'.encode('utf-8')
link_text = unicode(link.get_text()).encode('utf-8')
link_target = link['href'].encode('utf-8')
line_out = unicode(table_row.format(link_text, link_target))

所有这些对 .encode('utf-8') 的显式调用都是我试图完成这项工作的尝试,但它们似乎没有帮助——我很可能完全误解了 Python 2.7 如何处理 Unicode 字符串。

反正。这工作正常,直到它在 URL 中遇到 U+2013(是的,真的)。那时它会爆炸:

Traceback (most recent call last):
File "./test2.py", line 30, in <module>
  line_out = unicode(table_row.encode('utf-8').format(link_text, link_target.encode('utf-8')))
  UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 79: ordinal not in range(128)

大概 .format(),甚至应用于 Unicode 字符串,正在玩傻瓜并尝试执行 .decode() 操作。由于 ASCII 是默认值,它正在使用它,当然它不能将 U+2013 映射到 ASCII 字符,因此......

选项似乎是删除它或将其转换为其他东西,但我真正想要的是简单地保留它。最终(这只是一个小测试用例)我需要能够展示可工作的可点击链接。

BS3 文档建议将默认编码从 ASCII 更改为 UTF-8,但阅读有关类似问题的评论,这看起来是一个非常糟糕的主意,因为它会弄乱字典。

没有使用 Python 3.2(这意味着没有 Django,我们正在考虑将其作为该项目的一部分),有什么方法可以使这项工作干净利落吗?

4

1 回答 1

11

首先,请注意您的两个代码示例在有问题的行的文本上存在分歧:

line_out = unicode(table_row.encode('utf-8').format(link_text, link_target.encode('utf-8')))

对比

line_out = unicode(table_row.format(link_text, link_target))

第一个是来自回溯的那个,所以它是要查看的。假设您的第一个代码示例的其余部分是准确的,table_row是一个字节字符串,因为您采用了一个 unicode 字符串并对其进行了编码。字节字符串无法编码,因此 Python 2 通过将 table_row 解码为 ascii 来隐式地将 table_row 从字节字符串转换为 unicode。因此出现错误消息“来自 ascii 的 UnicodeDecodeError”。

您需要决定哪些字符串将是字节字符串,哪些将是 unicode 字符串,并对其进行纪律处分。我建议尽可能将所有文本保留为 Unicode 字符串。

这是我在 PyCon 上的一个演示文稿,它解释了这一切:实用的 Unicode,或者,我如何停止痛苦?

于 2012-06-13T03:12:36.423 回答