lxml 无法解析 <table>?
我想解析HTML中的表格,但我发现lxml解析不了,这是怎么回事呢?
# -*- coding: utf8 -*-
import urllib
import lxml.etree
keyword = 'lxml+tutorial'
url = 'http://www.baidu.com/s?wd='
if __name__ == '__main__':
page = 0
link = url + keyword + '&pn=' + str(page)
f = urllib.urlopen(link)
content = f.read()
f.close()
tree = lxml.etree.HTML(content)
query_link = '//table'
info_link = tree.xpath(query_link)
print info_link
打印的结果就是一个空列表 []...
2 个回答
2
我看到你代码里有几个地方可以改进,不过针对你的问题,我有以下建议:
用
lxml.html.parse(link)
来代替lxml.etree.HTML(content)
,这样可以让一些自动处理的功能正常工作。(比如,正确处理头部的字符编码声明)试试用
tree.findall(".//table")
而不是tree.xpath("//table")
。我不确定这样做是否会有区别,但我刚刚在自己的项目中用这个语法没有问题,而且它也能和非LXML的ElementTree API兼容。
还有一个主要的建议是,使用Python内置的函数来构建URL,这样你可以确保你构建的URL在任何情况下都是有效的,并且正确转义。
如果LXML找不到表格,而浏览器却显示有表格,我只能想象可能是这三种问题之一:
- 请求错误。LXML获取的页面里没有表格。(比如,错误404或500)
- 解析错误。页面的某些内容让
lxml.etree.HTML
在直接调用时感到困惑。 - 需要JavaScript。也许这个表格是客户端生成的。
3
lxml的文档上说:“解析损坏的HTML的能力完全依赖于libxml2的恢复算法。如果你发现某些文档损坏得太厉害,以至于解析器无法处理,那不是lxml的错。也不能保证最终得到的树结构会包含原始文档中的所有数据。解析器在努力解析时,可能会不得不放弃一些严重损坏的部分。”
果然,百度返回的HTML是无效的:W3C的验证工具报告了“173个错误,7个警告”。我不知道(也没有调查过)这些具体的错误是否导致了你在使用lxml时遇到的问题,因为我认为你用lxml来解析“野生”的HTML(几乎总是无效的)这个策略是注定要失败的。
要解析无效的HTML,你需要一个实现了(非常奇怪的!)HTML错误恢复算法的解析器。所以我建议用html5lib来替换lxml,它可以毫无问题地处理百度的无效HTML:
>>> import urllib
>>> from html5lib import html5parser, treebuilders
>>> p = html5parser.HTMLParser(tree = treebuilders.getTreeBuilder('dom'))
>>> dom = p.parse(urllib.urlopen('http://www.baidu.com/s?wd=foo').read())
>>> len(dom.getElementsByTagName('table'))
12