xpath指定多列的方法
How to specify multiple column by xpath
我想从 HTML 中获取多个 table 数据,如下所示:
html = <<EOF
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
</table>
EOF
我想从中获取两个数据:
noko = Nokogiri::HTML(html)
noko.xpath("//tr[1]/td[2]").text #=> "2"
noko.xpath("//tr[1]/td[3]").text #=> "3"
我对这段代码的期望是“23”,但return是“123”。
我怎样才能使用 xpath 只得到“23”?
noko.xpath("//tr[1]/td[2 and 3]").text
有多种方法可以解决这个问题。一个是:
require 'nokogiri'
html = <<EOF
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
</table>
EOF
noko = Nokogiri::HTML(html)
p noko.xpath("//tr[1]/td[position()= 2 or position() = 3]").map(&:text).join
# => 23
# another way
p noko.xpath("//tr[1]/td[2]", "//tr[1]/td[3]").map(&:text).join
# => 23
如果您不依赖 XPath,可以使用 CSS:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOF)
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
</table>
EOF
td_data = doc.search('tr').map { |tr|
tr.search('td:nth-child(2), td:nth-child(3)').map(&:text)
}
td_data # => [["2", "3"], ["5", "6"]]
或者对于较旧的、不太兼容的浏览器:
td_data = doc.search('tr').map { |tr|
tr.search('td:first-child + td, td:first-child + td + td').map(&:text)
}
td_data # => [["2", "3"], ["5", "6"]]
如果您需要返回的值是 "23"
and/or "56"
使用:
td_data.map(&:join) # => ["23", "56"]
尽管我不明白为什么这会过于有用。
怎么样:
doc.search('tr[1] td:gt(1)').text
#=> "23"
使用position()
使用xpath获取几个不同位置索引的元素,例如:
//tr[1]/td[position()=2 or position()=3]
您还可以使用 xpath 联合运算符 (|
) 组合多个 xpath 表达式,如下所示:
//tr[1]/td[2] | //tr[1]/td[3]
我更喜欢前一种方式,但联合可能是不同情况下唯一的选择,所以值得一提。
我想从 HTML 中获取多个 table 数据,如下所示:
html = <<EOF
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
</table>
EOF
我想从中获取两个数据:
noko = Nokogiri::HTML(html)
noko.xpath("//tr[1]/td[2]").text #=> "2"
noko.xpath("//tr[1]/td[3]").text #=> "3"
我对这段代码的期望是“23”,但return是“123”。 我怎样才能使用 xpath 只得到“23”?
noko.xpath("//tr[1]/td[2 and 3]").text
有多种方法可以解决这个问题。一个是:
require 'nokogiri'
html = <<EOF
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
</table>
EOF
noko = Nokogiri::HTML(html)
p noko.xpath("//tr[1]/td[position()= 2 or position() = 3]").map(&:text).join
# => 23
# another way
p noko.xpath("//tr[1]/td[2]", "//tr[1]/td[3]").map(&:text).join
# => 23
如果您不依赖 XPath,可以使用 CSS:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOF)
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
</table>
EOF
td_data = doc.search('tr').map { |tr|
tr.search('td:nth-child(2), td:nth-child(3)').map(&:text)
}
td_data # => [["2", "3"], ["5", "6"]]
或者对于较旧的、不太兼容的浏览器:
td_data = doc.search('tr').map { |tr|
tr.search('td:first-child + td, td:first-child + td + td').map(&:text)
}
td_data # => [["2", "3"], ["5", "6"]]
如果您需要返回的值是 "23"
and/or "56"
使用:
td_data.map(&:join) # => ["23", "56"]
尽管我不明白为什么这会过于有用。
怎么样:
doc.search('tr[1] td:gt(1)').text
#=> "23"
使用position()
使用xpath获取几个不同位置索引的元素,例如:
//tr[1]/td[position()=2 or position()=3]
您还可以使用 xpath 联合运算符 (|
) 组合多个 xpath 表达式,如下所示:
//tr[1]/td[2] | //tr[1]/td[3]
我更喜欢前一种方式,但联合可能是不同情况下唯一的选择,所以值得一提。