美丽的汤和Unicode问题

时间:2013-10-22 03:23:40

标签: python unicode beautifulsoup

我正在使用BeautifulSoup来解析一些网页。

偶尔会遇到如下所示的“unicode hell”错误:

在TheAtlantic.com [http://www.theatlantic.com/education/archive/2013/10/why-are-hundreds-of-harvard-students-studying-ancient-chinese-philosophy/280356/]

上查看本文的来源

我们在og:description meta属性中看到了这一点:

<meta property="og:description" content="The professor who teaches&nbsp;Classical Chinese Ethical and Political Theory claims, &quot;This course will change your life.&quot;" />

当BeautifulSoup解析它时,我看到了:

>>> print repr(description)
u'The professor who teaches\xa0Classical Chinese Ethical and Political Theory claims, "This course will change your life."'

如果我尝试将其编码为UTF-8,请注意:https://stackoverflow.com/a/10996267/442650

>>> print repr(description.encode('utf8'))
'The professor who teaches\xc2\xa0Classical Chinese Ethical and Political Theory claims, "This course will change your life."'

就在我认为我的所有unicode问题都得到控制的时候,我仍然不太了解发生了什么,所以我将提出几个问题:

1-为什么BeautifulSoup会将&nbsp;转换为\xa0 [拉丁字符集空间字符]?这个页面上的字符集和标题是UTF-8,我认为BeautifulSoup会为编码提取数据吗?为什么不用<space>取代?

2-是否有一种通用的方法来规范化空格以进行转换?

3-当我编码为UTF8时,\xa0成为\xc2\xa0的序列?

我可以通过unicodedata.normalize('NFKD',string)来管理所有内容,以帮助我找到我想去的地方 - 但我很想知道什么是错的,并避免将来出现这样的问题。

1 个答案:

答案 0 :(得分:24)

您没有遇到问题。一切都按照预期行事。

&nbsp;表示non-breaking space character。这不会被空格所取代,因为它不代表空间;它代表了一个不间断的空间。用空格替换它会丢失信息:在该空间发生的地方,文本呈现引擎不应该换行。

非中断空间的Unicode代码点是U + 00A0,它在Python中用Unicode字符串写成\xa0

U + 00A0的UTF-8编码是十六进制的两个字节序列C2 A0,或者用Python字符串表示\xc2\xa0编写。在UTF-8中,超出7位ASCII集的任何内容都需要两个或更多字节来表示它。在这种情况下,最高位组是第8位。这意味着它可以由双字节序列(二进制)110xxxxx 10xxxxxx表示,其中x是代码点的二进制表示的位。在A0的情况下,即10000000,或以UTF-8,11000010 10000000或C2 A0编码。

许多人在HTML中使用&nbsp;来获取通常的HTML空格折叠规则未折叠的空格(在HTML中,所有连续空格,制表符和换行符都被解释为单个空格,除非一个应用了CSS white-space rules,但这并不是他们的意图;它们应该被用于像名字这样的东西,比如“宫城先生”,你不希望在“先生”之间有换行符。和“宫城”。我不确定为什么在这种特殊情况下使用它;它似乎在这里不合适,但这更多的是你的源代码问题,而不是解释它的代码。

现在,如果你真的不关心布局,那么你不介意文本布局算法是否选择它作为一个包装的地方,但是想把它解释为一个常规空间,使用NFKD进行规范化是一个非常合理的答案(如果您更喜欢预先编写的重音符号,则为NFKC)。 NFKC and NFKD normalizations映射字符使得在大多数上下文中表示基本相同语义值的大多数字符被扩展出来。例如,扩展了连字(ffi - > ffi),将古老的长字符转换为s(s - > s),将罗马数字字符扩展为它们各自的字母(Ⅳ - > IV),并且破碎的空间转换为正常空间。对于某些字符,NFKC或NFKD规范化可能会丢失在某些情况下很重要的信息:ℌ和ℍ都会归一化为H,但在数学文本中可以用来指代不同的东西。