lxml无法解析?<table> </table>

时间:2010-11-04 03:45:19

标签: python parsing lxml web-crawler

我想在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 个答案:

答案 0 :(得分:3)

lxml的documentation says,“解析破坏的HTML的支持完全取决于libxml2的恢复算法。如果您发现文档严重破坏而解析器无法处理它们,则不是lxml的错误。还有不能保证生成的树将包含原始文档中的所有数据。解析器在努力保持解析时可能不得不丢弃严重损坏的部分。“

果然,百度返回的HTML无效:W3C validator reports“173错误,7个警告”。我不知道(并且没有调查过)这些特定的错误是否会给你的lxml带来麻烦,因为我认为你使用lxml解析HTML“在野外”(几乎总是无效的)的策略注定要失败

要解析无效的HTML,您需要一个实现(surprisingly bizarre!)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

答案 1 :(得分:2)

我看到几个代码可以改进的地方但是,对于你的问题,这是我的建议:

  1. 使用lxml.html.parse(link)而不是lxml.etree.HTML(content),这样所有“正常工作”的自动装置都可以启动。(例如,正确处理标题中的字符编码声明)

  2. 尝试使用tree.findall(".//table")而不是tree.xpath("//table")。我不确定它是否会有所作为,但我几小时前在我自己的项目中使用了这种语法而没有问题,作为奖励,它与非LXML ElementTree API兼容。

  3. 我建议的另一个主要问题是使用Python的内置函数来构建URL,这样您就可以确保您构建的URL在所有情况下都是有效且正确转义的。

    如果LXML找不到表格并且浏览器显示存在的表格,我只能想象它是这三个问题之一:

    1. 错误的请求。 LXML获取一个没有表格的页面。 (例如,错误404或500)
    2. 解析不好。关于页面的某些内容在直接调用时会混淆lxml.etree.HTML
    3. 需要Javascript。也许该表是在客户端生成的。