lxml树头和其他一些元素坏了

时间:2014-05-27 18:28:40

标签: python web-scraping lxml

我针对以下问题尝试了许多不同的解决方案,而我无法找到目前正在运行的解决方案。 我需要从几个网页的meta标签中获取一些信息。为此我发现lxml非常有用,因为我还需要使用xpath查找特定内容来解析它。 XPath在树上运行,然而,我有20%的网站(总共大约100个)不能工作,特别是头部似乎已经坏了。

tree = html.fromstring(htmlfrompage)  // using html from lxml package
head_object = tree.head               // access to head object from this webpage

在所有这些网站中,访问头对象(这只是xpath的快捷方式)失败并出现同样的错误:

print tree.head
IndexError: list index out of range

因为以下xpath失败:

self.xpath('//head|//x:head', namespaces={'x':XHTML_NAMESPACE})[0]

此xpath为空,因此访问第一个元素失败。我自己导航树和self.xpath(' // head')或self.xpath(' // html / head')甚至self.xpath(' // body')是空的。但是,如果我尝试直接在文档的任何位置访问元标记:

head = tree.xpath("//meta")
for meta_tag in head:
    print meta_tag.text  # Just printing something

它有效,所以它意味着metas不会连接到头部,但它们会在树中浮动。无论如何,头并不存在。当然,我可以尝试补丁"这个问题访问头部,如果我得到索引超出范围异常我可以导航metas找到我正在寻找的东西,但我期望lxml修复破坏的html(正如我在文档中读到的那样)。

是否有人有同样的问题并能以更好的方式解决它?

1 个答案:

答案 0 :(得分:1)

使用requests我可以很好地加载树:

>>> import requests
>>> from lxml import html
>>> r = requests.get('http://www.lanacion.com.ar/1694725-ciccone-manana-debera-declarar-carosso-donatiello-el-inquilino-de-boudou')
>>> tree = html.fromstring(r.content)
>>> tree.head
<Element head at 0x10681b4c8>

请注意您要将字节字符串传递给html.fromstring();不要使用r.text,因为它会以Unicode传递。

此外,如果服务器未在标头中指明编码,requests将回退到HTTP RFC默认值,即text/响应的ISO-8859-1。对于这个不正确的特定响应:

>>> r.headers['Content-Type']
'text/html'
>>> r.encoding
'ISO-8859-1'
>>> r.apparent_encoding  # make an educated guess
'utf-8'

这意味着r.text将使用Latin-1解码UTF-8数据,从而导致Unicode字符串解码错误,进一步使事情变得混乱。

另一方面,HTML解析器可以使用存在的<meta>标头来告诉它使用哪种编码:

>>> tree.find('.//meta').attrib
{'content': 'text/html; charset=utf-8', 'http-equiv': 'Content-Type'}