gpt4 book ai didi

java - 使用 jsoup 提取 `th` header 显示特定值的表

转载 作者:行者123 更新时间:2023-11-30 03:49:52 26 4
gpt4 key购买 nike

当处理一堆困惑的嵌套表时,我们如何使用 jsoup 提取特定的一个表?

以下面的 HTML 为例,一堆表格。向下扫描后半部分,找到两个关键表,每个表都有第 th 单元格,显示 DOGCAT

有时我想要狗 table ,有时我想要猫 table 。可能有十几个(“鸟”、“老鼠”、“仓鼠”等)。猫 table 可能比狗 table 嵌套得更深。所以我不能使用任何关于“第一个”或“最后一个”的技巧。我必须查看第 th 单元格的值,然后获取直接包含的表。

以下jsoup代码给我两个元素:

 Elements elements = document.select( "table:has(tbody > tr > th  > b:containsOwn(CAT))" );

通过这一行,我得到两个元素而不是一个:

  • 我想要的 table 。
  • 包含我想要的表的外表。

此时,我的解决方法是检查长度,然后选择较短的长度。但一定有更好的方法。

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>title</title>
</head>
<body>
<!-- page content -->
<table> <!--Outer table. Do not want this.-->
<tbody>
<tr>
<td>

<table>
<tbody>
<tr>
<th><b>DOG</b></th> <!-- DOG in header -->
</tr>
<tr>
<td>X</td>
<td>7</td>
</tr>
</tbody>
</table>

</td>
<td>

<table> <!-- I want this table because it contains a header ("th") displaying the value "CAT". -->
<tbody>
<tr>
<th><b>CAT</b></th> <!-- CAT in header -->
</tr>
<tr>
<td>A</td>
<td>1</td>
</tr>
</tbody>
</table>

</td>
</tr>
</tbody>
</table>
</body>
</html>
<小时/>

我还尝试了以下带有 jsoup 版本 1.7.3 的 Java 应用程序。

package com.example.jsoupexperiment;

import java.io.InputStream;
import java.util.Scanner;
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 ParseNestedTables
{
public static void main( String[] args )
{
System.out.println( "Running main method of ParseNestedTables class." );
InputStream stream = ParseNestedTables.class.getResourceAsStream( "/bogus.html" );
Scanner scan = new Scanner( stream );
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))" );
int countElements = elements.size(); // Hoping for 1, but getting 2.
System.out.println( "Found " + countElements + " elements. Dumping… \n\n" );

for ( Element element : elements ) {
System.out.println( "Element…\n" + element.toString() + "\n\n" );
}

}
}

但它返回两个元素而不是一个:

  1. 包含所需表的外表。
  2. 所需的表格。

另一个问题是,虽然我不太明白eq selector的行为,如果它只是在层次结构中同一点上彼此相邻的兄弟元素中进行选择,那么即使它在此示例中有效,也不是正确的答案。在我的问题的实际应用程序中,这些表可以任意嵌套在任意数量的其他表中。其他表与页面布局相关,与我所需的表没有直接逻辑连接。

最佳答案

解决方法:查找目标值,向上提升层次结构

另一种解决方法。这不是一个真正的答案,因为它没有改进 jsoup 选择器。

我们通过第 th 标题单元格的值知道我们想要哪个表。因此找到该元素,然后向后工作。沿着元素层次结构(DOM 树)向上,经过 trtbody,直到到达 table。我们知道这是拥有第目标的直接表。我们避免使用外部嵌套表。

关键代码包括查找第个单元格:

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.jsoupexperiment;

import java.io.InputStream;
import java.util.Scanner;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class ParseNestedTables
{
public static void main ( String[] args )
{
System.out.println( "Running main method of ParseNestedTables class." );
InputStream stream = ParseNestedTables.class.getResourceAsStream( "/bogus.html" );
Scanner scan = new Scanner( stream );
StringBuilder sb = new StringBuilder();
while ( scan.hasNextLine() ) {
sb.append( scan.nextLine() + "\n" );
}

Document document = Jsoup.parse( sb.toString() );
Elements elements = document.select( "th > b:containsOwn(CAT)" ); // Start by finding the desired table's target "th" element.
int countElements = elements.size();
switch ( countElements ) {
case 0:
System.out.println( "ERROR: Found no elements." );
break;
case 1:
System.out.println( "GOOD: Found 1 element." );
Element element = elements.first();

// Loop up the hierarchy of elements (the DOM tree) until we find our desired "table" element or until we get a null.
while ( ! ( ( element == null ) || ( element.tagName().equalsIgnoreCase( "table" ) ) ) ) {
element = element.parent();
}

System.out.println( "Found Element:\n" + element.toString() );
break;
default:
System.out.println( "ERROR: Found multiple elements: " + countElements );
break;
}
}
}

关于java - 使用 jsoup 提取 `th` header 显示特定值的表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24719049/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com