Java j组选择器:h2后的第二个div
我有以下HTML:Java j组选择器:h2后的第二个div,java,html,css-selectors,jsoup,Java,Html,Css Selectors,Jsoup,我有以下HTML: <html> <body> ... <h2> Blah Blah 1</h2> <p>blah blah</p> <div> <div> <table> <tbody> <tr><th>Col 1 Header</th><th>
<html>
<body>
...
<h2> Blah Blah 1</h2>
<p>blah blah</p>
<div>
<div>
<table>
<tbody>
<tr><th>Col 1 Header</th><th>Col 2 Header</th></tr>
<tr><td>Line 1.1 Value</td><td>Line 2.1 Header</td></tr>
<tr><td>Line 2.1 Value</td><td>Line 2.2 Value</td></tr>
</tbody>
</table>
</div>
</div>
<div>
<div>
<table>
<tbody>
<tr><th>Col 1 Header T2</th><th>Col 2 Header T2</th></tr>
<tr><td>Line 1.1 Value T2</td><td>Line 2.1 Header T2</td></tr>
<tr><td>Line 2.1 Value T2</td><td>Line 2.2 Value T2</td></tr>
</tbody>
</table>
</div>
</div>
<h2> Blah Blah 2</h2>
<div>
<div>
<table>
<tbody>
<tr><th>XCol 1 Header</th><th>XCol 2 Header</th></tr>
<tr><td>XLine 1.1 Value</td><td>XLine 2.1 Header</td></tr>
<tr><td>XLine 2.1 Value</td><td>XLine 2.2 Value</td></tr>
</tbody>
</table>
</div>
</div>
<p>blah blah</p>
<div>
<div>
<table>
<tbody>
<tr><th>XCol 1 Header T2</th><th>XCol 2 Header T2</th></tr>
<tr><td>XLine 1.1 Value T2</td><td>XLine 2.1 Header T2</td></tr>
<tr><td>XLine 2.1 Value T2</td><td>XLine 2.2 Value T2</td></tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
但要提取第二个,将“Blah 1”替换为“Blah 2”将不起作用,因为“p”标记位于其他位置,因此静态选择器将是:
h2:contains(Blah 2) + div + p +div
我需要的是一个单一的选择器公式,在这个公式中,无论p块在哪里,只要改变文本,它就会工作
我尝试了几种方法:
喜欢类型的选择器n也不起作用,因为我知道DIV的位置只对应于h2,它不是DIV的父亲,而是前面的兄弟姐妹
请帮忙我有两个办法来实现这一点。
第一个是删除每个
,然后只需选择“h2:contains(“+text+”)+div+div”
。请小心,只有当您确定您的
不包含任何
时才使用它。否则它将缺少一些内容
public void execute1(String html) {
Document doc = Jsoup.parse(html);
// first approach: remove every <p> to simplify document
Elements paragraphs = doc.select("p");
for (Element paragraph : paragraphs) {
paragraph.remove();
}
// then one selector will return what you want in both cases
System.out.println(selectSecondDivAfterH2WithText(doc, "Blah 1"));
System.out.println(selectSecondDivAfterH2WithText(doc, "Blah 2"));
}
private Element selectSecondDivAfterH2WithText(Document doc, String text) {
return doc.select("h2:contains(" + text + ")+div+div").first();
}
我还有第三个想法,使用类型为(2)的第n个div:h2:contains(“+text+”)。它对第一种情况有效,但对第二种情况无效,可能是因为div之间有一个
。一个简单的方法是使用逗号(,
)查询运算符,它在选择器之间执行OR。因此,您可以将P
标记所在位置的两种变体组合起来
h2:contains(Blah 2) + div ~ div, h2:contains(Blah 2) ~ div + div
这里是操场上的一个例子。为了澄清“包含给定文本”:您是否希望选择h2标记后面的第二个div,该标记本身包含“blah2”?如果是,p标签的功能是什么?使用支持xpath的库(如xsoup)将更容易做到这一点;这是一个选项吗?我需要迭代来提取H2后面的第二个DIV,该H2包含在每次迭代时更改的文本。你完全正确,杰克;Xpath很好,但不幸的是,我使用的是基于jsoup的工具:(嗨,Jonathan,我最后写了一些Java代码,因为我无法列举所有可能的情况,因为提供的代码仅用于testin,但我需要废弃的HTM页面比itHy Kristian复杂得多,我想避免使用Java,但最终没有编码就无法做到:)
public void execute2(String html) {
Document doc = Jsoup.parse(html);
System.out.println(selectSecondDivAfterH2WithText2(doc, "Blah 1"));
System.out.println(selectSecondDivAfterH2WithText2(doc, "Blah 2"));
}
private Element selectSecondDivAfterH2WithText2(Document doc, String text) {
int counter = 2;
// find h2 with given text
Element h2 = doc.select("h2:contains(" + text + ")").first();
// select every sibling after this h2 element
Elements siblings = h2.nextElementSiblings();
// loop over them
for (Element sibling : siblings) {
// skip everything that's not a div
if (sibling.tagName().equals("div")) {
// count how many divs left to skip
counter--;
if (counter == 0) {
// return when found nth div
return sibling;
}
}
}
return null;
}
h2:contains(Blah 2) + div ~ div, h2:contains(Blah 2) ~ div + div