Python、lxml 和 xpath - HTML 表格解析

5 投票
2 回答
11935 浏览
提问于 2025-04-15 15:07

我刚接触lxml,也刚开始学Python,遇到了一些问题,找不到解决办法:

我需要导入几个表格,每个表格有3列,行数不固定,从第三行开始。

如果任何一行的第二列是空的,这一行就会被丢弃,整个表格的处理也会停止。

下面的代码可以很好地打印出表格的数据(但我之后无法重复使用这些数据):

from lxml.html import parse

def process_row(row):  
    for cell in row.xpath('./td'):  
        print cell.text_content()  
        yield cell.text_content()  

def process_table(table):  
    return [process_row(row) for row in table.xpath('./tr')]

doc = parse(url).getroot()  
tbl = doc.xpath("/html//table[2]")[0]  
data = process_table(tbl)  

这段代码只打印了第一列 :(

for i in data:  
    print i.next()

而这段代码只导入了第三行,而没有后面的行。

tbl = doc.xpath("//body/table[2]//tr[position()>2]")[0]

有没有人知道一个好的方法,可以把第三行及其后的所有数据导入到tbl中,并复制到一个数组里,这样就可以在没有lxml依赖的情况下进行处理?

提前谢谢大家的帮助,Alex

2 个回答

0

你需要用一个循环来访问每一行的数据,像这样:

for row in data:  
    for col in row:
        print col

你只调用一次next(),就只会得到第一项,所以你只看到一列数据。

要注意,由于生成器的特性,你只能访问它一次。如果你把调用 process_row(row) 改成 list(process_row(row)),那么生成器就会被转换成一个可以重复使用的列表。

更新:如果你只需要从第三行开始的数据,可以用 data[2:]

2

这是一个生成器:

def process_row(row):  
     for cell in row.xpath('./td'):  
         print cell.text_content()  
         yield cell.text_content() 

你在调用它的时候,以为它会返回一个列表。其实并不是。它在某些情况下表现得像一个列表:

print [r for r in process_row(row)]

但这只是因为生成器和列表在for循环中使用时,展现出来的接口是一样的。使用它的场景如果只评估一次,比如:

return [process_row(row) for row in table.xpath('./tr')]

每次新的row值时,都会调用生成器的新实例,只返回第一个结果。

所以这是你的第一个问题。第二个问题是你期待:

tbl = doc.xpath("//body/table[2]//tr[position()>2]")[0]

能给你第三行及之后的所有行,但它实际上只把tbl设置为第三行。其实,调用xpath确实返回了第三行及之后的所有行。问题出在最后的[0]上,这让你困惑了。

撰写回答