【问题标题】:Extracting html tags between header tags using jsoup or regex使用 jsoup 或正则表达式在标题标签之间提取 html 标签
【发布时间】:2015-04-27 07:25:59
【问题描述】:

嗨,我在 html 文件解析中有一个场景。我正在使用 jsoup 解析 html 文件,解析后我想提取标题标签 (h1,h3,h4)。我使用了 doc.select() 但它只会返回标头标签值,但我的要求是我应该提取 h1 到 h3 或 h4 之间的标签,反之亦然。

<h4>SECTION 2</h4>
<p>some thing h4.....</p>
<p>some thing h4.....</p>
<p>some thing h4.....</p>
<h3>lawsuit</h3>
<p>some thing h3.....</p>
<p>some thing h3.....</p>
<p>some thing h3.....</p>
<h1>header one </h1>

所以这里首先搜索html字符串是否包含任何H1,H3,H4。 这里我们有 h4,所以包括 h4 它应该搜索下一个 h1 或 h3,直到 h3 我们提取字符串并将其放在单独的 html 文件中。

第一个 html 文件包含

<h4>SECTION 2</h4>
<p>some thing h4.....</p>
<p>some thing h4.....</p>
<p>some thing h4.....</p>

第二个html文件包含

<h3>lawsuit</h3>
<p>some thing h3.....</p>
<p>some thing h3.....</p>
<p>some thing h3.....</p>

第三个html文件包含

<h1>header one </h1>
....
....
....

这里的 html 字符串是动态的,所以我想写一个正则表达式来实现这个上下文,因为我是 java 新手,我不知道如何实现这个。 现在我使用子字符串,但我需要一个通用的方法,无论是正则表达式还是 jsoup 本身。

我试过的代码是。

try {
    File sourceFile = new File("E://data1.html");
    org.jsoup.nodes.Document doc = Jsoup.parse(sourceFile, "UTF-8");
    org.jsoup.nodes.Element elements = doc.body();
    String elementString = StringUtils.substringBetween(elements.toString(),"<h4>", "<h3>");
    System.out.println("elementString::"+elementString);
    File destinationFile = new File("E://sample.html");
    BufferedWriter htmlWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(destinationFile), "UTF-8"));
    htmlWriter.write(elementString);
    htmlWriter.close();
    System.out.println("Completed!!!");
} catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

请帮助我实现这一目标。

【问题讨论】:

  • 适用于您的第一个 html 的基本正则表达式是 here。虽然不能让它工作得很好。

标签: java regex string jsoup


【解决方案1】:

请不要使用正则表达式从 Xml 或 HTML 文档中提取元素。正则表达式对大型文档有限制。

改为使用 XPath 来查询文档。例如尝试查看this * 问题。您可以使用管道运算符 |在 OR 中有多个条件。

类似的东西应该可以工作:

//h1/following-sibling::p |
//h2/following-sibling::p |
//h3/following-sibling::p |
...

【讨论】:

  • 感谢您的回复。这不适用于我想在两个标签之间提取数据的场景。我的文档是动态的,我无法确定前面的标签。它可以是任何一个,它面向 h1 为首先,或者它可能是 h2 或 h3。所以,如果我错了,请给我一些其他选择或纠正我。
  • @VelNaga 您是否使用我们提供给您的提示解决了您的问题?
  • 我使用您的解决方案解决了这个问题。很抱歉没有接受答案。现在我接受并投票。谢谢!!!
【解决方案2】:

您可能正在寻找this。您可以在选择所需元素后使用此功能。

如果你使用的是 Jsoup,那么在 dom 操作的情况下,你不必(实际上不需要)使用正则表达式。

Elements heads = body.select('h1');
// iterate and get inner html of that elements by
String html = head.html();

-- 编辑--

误解了问题;

您可以确定 h 标签的索引并使用getElementsByIndexGreaterThan。其余的都是一样的。

-- 编辑 2--

针对您的特殊情况;您可以在找到第一个 h 元素后进行迭代:

  Elements elements = doc.select("h1,h2,h3,h4,h5");
  for (Element element : elements) {
     StringBuilder sb = new StringBuilder(element.toString());

     Element next = element.nextElementSibling();
     while (next != null && !next.tagName().startsWith("h")) {
        sb.append(next.toString()).append("\n");
        next = next.nextElementSibling();
     }
     System.out.println(sb);

  }

应该适合你。

【讨论】:

  • 问题是 OP 想要在 标题之后获取文本,所以这行不通。
  • @px5x2 感谢您的回复。但请您详细说明我无法联系到您。