【问题标题】:Parse unicode characters from HTML element in Python从 Python 中的 HTML 元素解析 unicode 字符
【发布时间】:2013-11-24 17:05:37
【问题描述】:

我有以下代码来解析 HTML 网站。这将返回一个 HTML 元素对象。我想在多台机器上运行这段代码,所以当有人试图从代理后面运行它时,实现代理对我来说很重要。

from lxml.html import parse

def parsepage(url):
if proxy:
    proxy_support = urllib2.ProxyHandler({"http":proxy})
    opener = urllib2.build_opener(proxy_support,urllib2.HTTPHandler)
    urllib2.install_opener(opener)
    conn = urllib2.urlopen(url)
    site = parse(conn).getroot()
else:
    site = parse(url).getroot()
return site

在它返回 HTML 元素后,我使用这样的 Xpath 表达式从对象中获取数据:

element = site.xpath(expression)

问题是结果包含非 unicode 数据,其中包含转义字符。例如:

\xe1ci\xf3s 组合

我也尝试过这个实现,但是这个给我一个错误:

def parsepage(url):
if proxy:
    proxy_support = urllib2.ProxyHandler({"http":proxy})
    opener = urllib2.build_opener(proxy_support,urllib2.HTTPHandler)
    urllib2.install_opener(opener)
    conn = urllib2.urlopen(url)
    rawdata = conn.read()
    parser = etree.HTMLParser(encoding="utf-8")
    site = etree.HTML(rawdata, parser=parser)
else:
    site = parse(url).getroot()
return site

错误信息是:

'utf8' decode 无法解码位置 4 中的字节 0xf3:无效的继续字节

该网站使用 iso-8859-2 字符集。

有没有一种方法可以使用上面列出的解析方法之一将非 unicode 字符转换为 unicode?或者,也许我弄错了,我得到了正确格式的数据,但我的表示有问题。

我应该改用 lxml.fromstring 并使用 encoding 参数吗?

谢谢, g0m3z

解决方案:

实际上我的代码没有问题,但数据的表示。第一个代码实现工作正常。

我将结果加载到字典中,当我一次打印整个字典时,它会错误地显示 unicode 字符。但是,如果我仅根据键打印结果字典的一项,则它正确表示 unicode 字符。所以它有效!有趣的。感谢此线程上的每个人提供宝贵的 cmets!

【问题讨论】:

  • 既然知道是iso-8859-2,为什么还要告诉解析器编码是utf-8?尝试使用parser = etree.HTMLParser(encoding="iso-8859-2") 看看是否能解决您的问题。
  • 对不起,我忘了提到我尝试了 iso-8859-2 编码,但我仍然有转义字符
  • +1 用于实际使用解析器,而不是像 90% 的 SO 用户喜欢的那样尝试使用正则表达式解析 HTML。

标签: python unicode html-parsing lxml


【解决方案1】:

您应该从 HTTP 标头(或 HTML 元标记)中读取实际的字符编码,而不是猜测它。这样可以避免解码错误。

【讨论】:

  • 对不起,我忘了提到我尝试了 iso-8859-2 编码,但我仍然得到了转义字符。
  • 理论上应该是这样的。不幸的是,托管公司通常不让网站管理员能够更改 HTTP 标头中的字符集信息,此外,网页设计师在使用元元素时经常不一致(责备货物崇拜编码)。除非您知道该站点在这些领域是合规的,否则您可能必须尝试自动检测编码(在类似的情况下,我们有一个按顺序尝试的编码列表,采用第一个解码而不会引发异常的编码。不是一个很好的解决方案;事后看来,我可能会使用 chardet 或一些类似的库)
  • @Gomez 正如我所说,不要试图猜测它,至少尝试推断它。
  • @brjaga 悲伤,但真实。但这也为您根本无法猜测编码的情况留下了空间。但我不知道 OP 在这些情况下会如何处理。
  • @brjaga 感谢您的及时回复!在这种情况下,我猜代理可能有问题。我会尝试绕过代理运行它并让你知道结果。
【解决方案2】:

您可以尝试使用库来解析请求。我推荐你 BeautifulSoup。这将处理编码的所有问题,并且非常易于使用。

【讨论】:

  • 谢谢,但我想保持简单和快速。我发现 lxml 非常快。
猜你喜欢
  • 2013-09-13
  • 1970-01-01
  • 1970-01-01
  • 2011-12-13
  • 2012-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-24
相关资源
最近更新 更多