3

当我得到一个网页时,我使用 UnicodeDammit 将其转换为 utf-8 编码,就像:

import chardet
from lxml import html
content = urllib2.urlopen(url).read()
encoding = chardet.detect(content)['encoding']
if encoding != 'utf-8':
    content = content.decode(encoding, 'replace').encode('utf-8')
doc = html.fromstring(content, base_url=url)

但是当我使用时:

text = doc.text_content()
print type(text)

输出是<type 'lxml.etree._ElementUnicodeResult'>。为什么?我认为这将是一个 utf-8 字符串。

4

2 回答 2

7

lxml.etree._ElementUnicodeResult是一个继承自的类unicode

$ pydoc lxml.etree._ElementUnicodeResult

lxml.etree._ElementUnicodeResult = class _ElementUnicodeResult(__builtin__.unicode)
 |  Method resolution order:
 |      _ElementUnicodeResult
 |      __builtin__.unicode
 |      __builtin__.basestring
 |      __builtin__.object

在 Python 中,拥有从基本类型扩展的类以添加一些特定于模块的功能是相当普遍的。将对象视为常规 Unicode 字符串应该是安全的。

于 2012-12-21T03:31:46.550 回答
1

您可能希望跳过重新编码步骤,因为lxml.html它将自动使用源文件中指定的编码,并且只要它最终成为有效的 unicode,也许没有理由担心它最初是如何编码的。

除非您的项目是如此的小和非正式,以至于您可以确定您永远不会遇到 8 位字符串(即它始终是 7 位 ASCII,没有特殊字符的英文),否则明智的做法是尽早将您的文本转换为 unicode(就像检索后一样)并保持这种状态,直到您需要将其序列化以写入文件或通过套接字发送。

您看到的原因<type 'lxml.etree._ElementUnicodeResult'>是因为lxml.html.fromstring()它会自动为您执行解码步骤。请注意,这意味着您上面的代码不适用于使用 UTF-16 编码的页面,例如,因为 8 位字符串将以 UTF-8 编码,但 html 仍会显示 utf-16

<meta http-equiv="Content-Type" content="text/html; charset=utf-16" />

并且 lxml 将尝试根据 utf-16 编码规则对字符串进行解码,从而在短时间内引发我期望的异常。

如果您希望将输出序列化为UTF-8编码的 8 位字符串,您只需要以下内容:

>>> text = doc.text_content().encode('utf-8')
>>> print type(text)
<type 'str'>
于 2013-02-18T01:04:48.687 回答