python xpath 一些但不是所有的列 table
python xpath some but not all columns of a table
不幸的是,我是 XPath 的初学者,并不完全确定 ir 是如何工作的。对于我的一个项目,我正在寻找一种方法来解析 9 列中的 5 列 table。这是我到目前为止的工作:
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)
看起来很多数据都包含在 link (a) 标签中,因此当您请求文本节点 children 时,您找不到任何数据,因为您需要更深入一层。
而不是
/text()
做
//text()
两个斜杠表示 select 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()
但此表达式存在风险,因为它会选取出现在 table 中任何位置的 td 元素(前提是它们是第 1、4、5、6 或 7 列),而不是就在 body 中的行中。但是,在您的目标中,这将起作用。
另请注意,[position()=1]
之类的表达式不是必需的。您可以将其缩短为 [1]
。如果您需要上下文节点以外的节点的位置,或者需要编写更复杂的 selection,就像我们在需要多个特定索引时所用的那样,您只需要位置函数。
不幸的是,我是 XPath 的初学者,并不完全确定 ir 是如何工作的。对于我的一个项目,我正在寻找一种方法来解析 9 列中的 5 列 table。这是我到目前为止的工作:
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)
看起来很多数据都包含在 link (a) 标签中,因此当您请求文本节点 children 时,您找不到任何数据,因为您需要更深入一层。
而不是
/text()
做
//text()
两个斜杠表示 select 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()
但此表达式存在风险,因为它会选取出现在 table 中任何位置的 td 元素(前提是它们是第 1、4、5、6 或 7 列),而不是就在 body 中的行中。但是,在您的目标中,这将起作用。
另请注意,[position()=1]
之类的表达式不是必需的。您可以将其缩短为 [1]
。如果您需要上下文节点以外的节点的位置,或者需要编写更复杂的 selection,就像我们在需要多个特定索引时所用的那样,您只需要位置函数。