python xpath一些但不是表的所有列

时间:2016-01-04 23:33:41

标签: python xpath lxml

不幸的是,我是XPath的初学者而不是完全确定如何工作。对于我的一个项目,我正在寻找一种解析9列表的5列的方法。这是我到目前为止所做的工作:

url="".join(["http://www.basketball-reference.com/leagues/NBA_2011_games.html"])

#getting the columns 4-7
page=requests.get(url)
tree=html.fromstring(page.content)
# the //text() is because some of the entries are inside <a></a>s
data = tree.xpath('//table[@id="games"]/tbody/tr/td[position()>3 and position()<8]//text()')

所以我的解决方法的想法是,只获得另一个列表,只获得第一列,然后将这两个列合并为一个额外的步骤,这似乎是无用的和不必要的。

到目前为止我尝试过的XPath

//table[@id="games"]/tbody/tr/td[position() = 1]/text() | //table[@id="games"]/tbody/tr/td[position()>3 and position()<8]//text()

这也不包括第一列(日期)。 (根据w3schools)|是连接两个XPath语句的运算符。

所以这是我现在的完整代码。然后,数据将被放入两个列表中。

希望我没有做任何太愚蠢的事情,谢谢你的帮助。

from lxml import html
import requests


url="".join(["http://www.basketball-reference.com/leagues/NBA_1952_games.html"])

page=requests.get(url)
tree=html.fromstring(page.content)
reg_data = tree.xpath('//table[@id="games"]/tbody/tr/td[position() = 1]/text() | //table[@id="games"]/tbody/tr/td[position()>3 and position()<8]//text()')
po_data = tree.xpath('//table[@id="games_playoffs"]/tbody/tr/td[position() = 1]/text() | //table[@id="games_playoffs"]/tbody/tr/td[position()>3 and position()<8]//text()')
n=int(len(reg_data)/5)

if int(year) == 2016:   
    for i in range(0,len(reg_data)):
        if len(reg_data[i])>3 and len(reg_data[i+1])>3:
            n = int((i)/5)
            break    

games=[]
for i in range(0,n):
    games.append([])
    for j in range(0,5):
        games[i].append(reg_data[5*i+j])

po_games=[]
m=int(len(po_data)/5)
if year != 2016:
    for i in range(0,m):
        po_games.append([])
        for j in range(0,5):
            po_games[i].append(po_data[5*i+j])

print(games)
print(po_games)

1 个答案:

答案 0 :(得分:1)

看起来很多数据都包含在链接(a)标记中,因此当您要求文本节点子节点时,您无法找到任何数据,因为您需要更深层次。

而不是

/text()

DO

//text()

两个斜杠意味着选择text()节点,这些节点是任何级别的后代。

您还可以将整个表达式合并到一起

//table[@id="games"]/tbody/tr/td[position() = 1 or (position()>3 and position()<8)]//text()

而不是有两个表达。

我们甚至可以进一步缩短

//table[@id="games"]//td[position() = 1 or (position()>3 and position()<8)]//text()

但是这个表达式存在风险,因为它会拾取出现在表格中任何位置的td元素(假设它们是第1,第4,第5,第6或第7列),而不仅仅是在正文中的行中。但是,在你的目标中,这将起作用。

另请注意,[position()=1]之类的表达式不是必需的。您可以将其缩短为[1]。如果您需要除上下文节点之外的节点的位置,或者需要编写更复杂的选择,就像我们在需要多于一个特定索引时那样,您只需要位置函数。