Java 从BR标记中提取文本

Java 从BR标记中提取文本,java,selenium,xpath,Java,Selenium,Xpath,我以前能够使用Selenium提取文本,但是我在提取标签之间的数字时遇到了麻烦。下面是html代码的示例 <DIV class="pagebodydiv"> <TABLE CLASS="datadisplaytable" SUMMARY="This table will display needed information." WIDTH="100%"> <TR> <TD CLASS="nttitle" scope="colgroup" >

我以前能够使用Selenium提取文本,但是我在提取标签之间的数字时遇到了麻烦。下面是html代码的示例

<DIV class="pagebodydiv">
    <TABLE  CLASS="datadisplaytable" SUMMARY="This table will display needed information." WIDTH="100%">
<TR>
<TD CLASS="nttitle" scope="colgroup" >Working Title</A></TD>
</TR>
<TR>
<TD CLASS="ntdefault">
 Further information on subject
<BR>
    3.000
<BR>
    2.000  
<BR>
<BR>
<BR>
<BR>
<BR>
More information
<BR>
<BR>
</TABLE>
Elements numInfo=doc.select(“br”)


但是,我一直遇到NosTouchElementException错误、InvalidSelectorException错误,或者它只是不返回任何内容。关于如何获取信息有什么想法吗?

我认为
BR
不被视为封闭标签,因此您将无法提取“封闭文本”。您可能需要提取包含在
TD CLASS=“ntdefault”
中的文本,所有
BR
将被翻译成换行符。然后,您必须执行字符串操作以仅提取您感兴趣的部分。

您实际上可以在

标记之间选择文本节点。在HTML(而不是XHTML)中,它们充当自动关闭标记(如

)。基于该行为,您可以使用以下方法选择在其前后具有

标记的所有文本节点:

//TABLE[@CLASS='datadisplaytable']/TR/TD[@CLASS="ntdefault"]
/text()[preceding-sibling::node()[1][self::BR] 
        and following-sibling::node()[1][self::BR]]

也将选择空白行和字符文本,这不是一个数字。

您可以在表达式末尾添加一个
[normalize space(.)!='']
(现在只返回三个节点)来删除空空间节点。您可以使用表达式末尾的位置谓词(
[1]
来选择所需的节点,以选择第一个节点

下面的表达式选择包含值
2.000
的文本节点:

//TABLE[@CLASS='datadisplaytable']/TR/TD[@CLASS="ntdefault"]
/text()[preceding-sibling::node()[1][self::BR] 
        and following-sibling::node()[1][self::BR]][normalize-space(.) != ''][2]
注意:我假设您的源代码实际上有大写的标记名,因为XPath中的
不同。我不确定Selenium在解析HTML时对此的容忍度有多高。

它可能有助于:

  WebElement table =driver.findElement(By.xpath("//table[@class='datadisplaytable']"));
   WebElement tbody=table.findElement(By.tagName("tbody"));
   List<WebElement> rows=tbody.findElements(By.tagName("tr"));
   System.out.println("Row  size:"+rows.size());
   ArrayList<String> list=new ArrayList<>();

   for(int i=0;i<rows.size();i++)
   {
     WebElement column = tbody.findElement(By.xpath("//table[@class='datadisplaytable']/tbody/tr[2]/td"));
     if(column.getText().trim().contains("."))
     {
        System.out.println("text : "+column.getText().trim());
        list.add(column.getText().trim());
     }

   }
WebElement table=driver.findElement(By.xpath(“//table[@class='datadisplaytable']);
WebElement tbody=table.findElement(按.tagName(“tbody”);
列表行=tbody.findElements(按.tagName(“tr”));
System.out.println(“行大小:+rows.size());
ArrayList=新建ArrayList();

对于(int i=0;我想知道答案。不幸的是,网页的其余部分包含多个具有相同类名的TD元素。你知道我可以通过第一个TD元素收集下一个TD元素的文本的方法吗?这现在是一个新问题!你需要使用正确的选择器;我个人更喜欢XPath。请阅读这里:我真的很喜欢这个网站,感谢您的参考。感谢您的回复。我尝试了您的两个建议,但仍然得到一个NosTouchElementException错误。我不太确定我做错了什么。这就是我如何使用代码的:WebElement info=driver.findElement(By.xpath(//TABLE[@CLASS='datadisplaytable']/TR/TD[@CLASS='ntdefault']/text()[前面的同级::node()[1][self::BR]和后面的同级::node()[1][self::BR]][normalize space(.!=''][2]”);…顺便问一下,您的意思是将ntdefault放在双引号中吗?简单引号和双引号没有区别(因为您使用双引号括住表达式,所以应该在其中使用单引号)selenium中的.XPath与HTML的操作不同,因为它必须处理不关闭的标记、实体等,这在XML中是无效的。但是,如果您的HTML非常糟糕,无法关闭
s和其他应关闭的元素,它可能会断开。在这种情况下,您应该尝试使用HTML解析器(例如JSoup)。您可以尝试简化该表达式,看看它是否有效。请尝试
//TD[@CLASS=“ntdefault”]/text()[2]
,它应该返回第二个文本节点(包含
3.000
),不幸的是,我不太了解Selenium如何在HTML中支持XPath。我知道不同的Selenium实现(RC、WebDriver等)可能会以不同的方式对待节点,因此尽管
text()[1]
表达式在XPath中完全有效,但在某些Selenium实现中可能会失败。此外,您应该检查它是否真的不区分大小写。它与大多数XPath实现
td
不匹配。它不区分大小写。此外,我删除了/text()[2]从xpath获取信息和两个数字。我将继续使用它,看看是否可以选择所需的数字。感谢Praveen的回复。这将为我提供整个表的信息。不过,我将继续使用它。顺便问一下,如果不同的表都具有相同的属性,您知道如何搜索它们吗相同的类名?所有不同的表都必须有一些独特的地方,否则selenium将无法区分不同的表。
  WebElement table =driver.findElement(By.xpath("//table[@class='datadisplaytable']"));
   WebElement tbody=table.findElement(By.tagName("tbody"));
   List<WebElement> rows=tbody.findElements(By.tagName("tr"));
   System.out.println("Row  size:"+rows.size());
   ArrayList<String> list=new ArrayList<>();

   for(int i=0;i<rows.size();i++)
   {
     WebElement column = tbody.findElement(By.xpath("//table[@class='datadisplaytable']/tbody/tr[2]/td"));
     if(column.getText().trim().contains("."))
     {
        System.out.println("text : "+column.getText().trim());
        list.add(column.getText().trim());
     }

   }