Java 使用jsoup提取“th”标题显示特定值的表
当处理一堆杂乱无章的嵌套表时,我们如何使用 以下面的HTML为例,它是一堆表格。在下半部分向下扫描两个关键表,每个表都有一个Java 使用jsoup提取“th”标题显示特定值的表,java,html,parsing,jsoup,Java,Html,Parsing,Jsoup,当处理一堆杂乱无章的嵌套表时,我们如何使用 以下面的HTML为例,它是一堆表格。在下半部分向下扫描两个关键表,每个表都有一个th单元格,显示DOG或CAT 有时我想要狗桌,有时想要猫桌。可能有十几只(鸟、老鼠、仓鼠等等)。cat表可能嵌套得比dog表更深。所以我不能使用任何有关“第一”或“最后”的技巧。我必须查看th单元格的值,然后获取立即包含表 以下代码为我提供了两个元素: Elements elements = document.select( "table:has(tbody >
th
单元格,显示DOG
或CAT
有时我想要狗桌,有时想要猫桌。可能有十几只(鸟、老鼠、仓鼠等等)。cat表可能嵌套得比dog表更深。所以我不能使用任何有关“第一”或“最后”的技巧。我必须查看th
单元格的值,然后获取立即包含表
以下代码为我提供了两个元素:
Elements elements = document.select( "table:has(tbody > tr > th > b:containsOwn(CAT))" );
通过这一行,我得到了两个元素,而不是一个:
- 我想要的那张桌子
- 包含我想要的表的外部表李>
标题
狗
X
7.
猫
A.
1.
我还使用jsoup版本1.7.3尝试了以下Java应用程序
package com.example.jsupexperiment;
导入java.io.InputStream;
导入java.util.Scanner;
导入org.jsoup.jsoup;
导入org.jsoup.nodes.Document;
导入org.jsoup.nodes.Element;
导入org.jsoup.select.Elements;
/**
*目的使用“jsoup”库测试嵌套表的解析,如
*关于StackOverflow.com问题的讨论:
* http://stackoverflow.com/q/24719049/642706
*标题:使用jsoup提取“th”标题显示特定值的表
*/
公共类ParseNesteTables
{
公共静态void main(字符串[]args)
{
System.out.println(“运行ParseNesteTables类的主方法”);
InputStream=ParseNesteTables.class.getResourceAsStream(“/bogus.html”);
扫描仪扫描=新扫描仪(流);
StringBuilder sb=新的StringBuilder();
while(scan.hasNextLine()){
sb.append(scan.nextLine()+“\n”);
}
//System.out.println(sb.toString());
Document Document=Jsoup.parse(sb.toString());
Elements=document.select(“表:等式(0):has(th:contains(CAT))”;
int countElements=elements.size();//希望为1,但得到2。
System.out.println(“找到”+countElements+“elements.Dumping…\n\n”);
for(元素:元素){
System.out.println(“元素…\n”+元素.toString()+”\n\n”);
}
}
}
但它返回两个元素而不是一个:
另一个问题是,虽然我不完全理解的行为,但如果它只是在层次结构中同一点上相邻的元素之间进行选择,那么即使在本例中有效,这也不是正确的答案。在我的问题的实际应用中,这些表可以任意嵌套在任意数量的其他表中。其他表与页面布局相关,与我想要的表没有直接的逻辑连接。我不知道,因为它似乎对我很好:
import java.util.Scanner;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
public class ThHeaderTest {
public static void main(String[] args) {
String resource = "thHeader.txt";
Scanner scan = new Scanner(ThHeaderTest.class.getResourceAsStream(resource));
StringBuilder sb = new StringBuilder();
while (scan.hasNextLine()) {
sb.append(scan.nextLine() + "\n");
}
// System.out.println(sb.toString());
Document document = Jsoup.parse(sb.toString());
Elements elements = document.select("table:eq(0):has(th:contains(CAT))");
System.out.println(elements);
}
}
解决方法:使用较短的元素
这不是一个正确的答案,因为它不会改进jsoup选择器。但这是一个实际的解决办法
由于问题是所需的表也将作为其外部嵌套父表返回,因此从逻辑上讲,我们知道所需表的HTML也将比外部表短
因此,解决方法是比较每一个发现的问题的长度。使用HTML长度最短的元素。解决方法:查找目标值,向上移动层次结构
另一个解决办法。这不是一个正确的答案,因为它不会改进jsoup选择器
我们通过它的th
头单元格的值知道需要哪个表。所以找到那个元素,然后倒转。沿着元素的层次结构(DOM树),经过tr
和tbody
,直到到达表。我们知道这是拥有目标th
的直接表。我们避免使用外部嵌套表
关键代码包括查找th
单元格:
Elements elements = document.select( "th > b:containsOwn(CAT)" );
…并循环查找每个父级:
Element element = elements.first();
while ( ! ( ( element == null ) || ( element.tagName().equalsIgnoreCase( "table" ) ) ) ) {
element = element.parent();
}
完整示例应用程序:
package com.example.jsupexperiment;
导入java.io.InputStream;
导入java.util.Scanner;
导入org.jsoup.jsoup;
导入org.jsoup.nodes.Document;
导入org.jsoup.nodes.Element;
导入org.jsoup.select.Elements;
公共类ParseNesteTables
{
公共静态void main(字符串[]args)
{
System.out.println(“运行ParseNesteTables类的主方法”);
InputStream=ParseNesteTables.class.getResourceAsStream(“/bogus.html”);
扫描仪扫描=新扫描仪(流);
StringBuilder sb=新的StringBuilder();
while(scan.hasNextLine()){
sb.append(scan.nextLine()+“\n”);
}
Document Document=Jsoup.parse(sb.toString());
Elements=document.sele
package com.example.jsoupexperiment;
import java.io.IOException;
import java.io.InputStream;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
/**
* PURPOSE To test parsing of nested tables using the "jsoup" library, as
* discussed on this StackOverflow.com question:
* http://stackoverflow.com/q/24719049/642706 Titled: Extract a table whose `th`
* header displays a certain value, using jsoup
*/
public class ParseNestedTables2 {
public static void main(String[] args) throws IOException {
System.out.println("Running main method of ParseNestedTables class.");
InputStream stream = ParseNestedTables2.class
.getResourceAsStream("/bogus.html");
Document document = Jsoup.parse(stream, "UTF-8", "http://example.com");
Elements elements = document.select("table table");
for (Element element : elements) {
if (element.select("th b:contains(CAT)").size() > 0) {
System.out
.println("table that have th contain selected text (CAT)");
System.out.println(element);
}
}
}
}