Jsoup:如何获取两个标题标签之间的所有HTML

4
我正在尝试获取两个h1标签之间的所有html内容。实际任务是根据h1(标题1)标签将html分割成帧(章节)。

感激任何帮助。

谢谢 Sunil


你是在尝试从中获取'<h1>abc</h1>' abc吗? - Rasel
我认为他想要获取所有内容到下一个h1,这样他就可以通过标题拆分页面。 - Tim Büthe
3个回答

6

如果您想获取并处理两个连续的h1标签之间的所有元素,可以使用siblings方法。以下是示例代码:

public static void h1s() {
  String html = "<html>" +
  "<head></head>" +
  "<body>" +
  "  <h1>title 1</h1>" +
  "  <p>hello 1</p>" +
  "  <table>" +
  "    <tr>" +
  "      <td>hello</td>" +
  "      <td>world</td>" +
  "      <td>1</td>" +
  "    </tr>" +
  "  </table>" +
  "  <h1>title 2</h1>" +
  "  <p>hello 2</p>" +
  "  <table>" +
  "    <tr>" +
  "      <td>hello</td>" +
  "      <td>world</td>" +
  "      <td>2</td>" +
  "    </tr>" +
  "  </table>" +
  "  <h1>title 3</h1>" +
  "  <p>hello 3</p>" +
  "  <table>" +
  "    <tr>" +
  "      <td>hello</td>" +
  "      <td>world</td>" +
  "      <td>3</td>" +
  "    </tr>" +
  "  </table>" +    
  "</body>" +
  "</html>";
  Document doc = Jsoup.parse(html);
  Element firstH1 = doc.select("h1").first();
  Elements siblings = firstH1.siblingElements();
  List<Element> elementsBetween = new ArrayList<Element>();
  for (int i = 1; i < siblings.size(); i++) {
    Element sibling = siblings.get(i);
    if (! "h1".equals(sibling.tagName()))
      elementsBetween.add(sibling);
    else {
      processElementsBetween(elementsBetween);
      elementsBetween.clear();
    }
  }
  if (! elementsBetween.isEmpty())
    processElementsBetween(elementsBetween);
}

private static void processElementsBetween(
    List<Element> elementsBetween) {
  System.out.println("---");
  for (Element element : elementsBetween) {
    System.out.println(element);
  }
}

你如何在打印标题名称之前获取它,并使标题按顺序出现。有没有什么好的地方可以寻找更多关于jsoup的示例。 - Sunil Ramu
我假设你想打印标题文本而不是它的名称(H1标题的名称始终为“H1”)。因此,在调用processElementsBetween(elementsBetween)之前,只需打印sibling.ownText()即可。我不确定你所说的“按顺序获取标题”的意思。JSoup文档:菜谱apidocs - MarcoS
1
这对于不属于标签的文本,如<h1/>this<h1/>将无法工作。这似乎是jsoup概念中的一个漏洞。 - Jarekczek

4

我不太了解Jsoup,但一个简单直接的方法可能是这样的:

public class Test {

    public static void main(String[] args){

        Document document = Jsoup.parse("<html><body>" +
            "<h1>First</h1><p>text text text</p>" +
            "<h1>Second</h1>more text" +
            "</body></html>");

        List<List<Node>> articles = new ArrayList<List<Node>>();
        List<Node> currentArticle = null;

        for(Node node : document.getElementsByTag("body").get(0).childNodes()){
            if(node.outerHtml().startsWith("<h1>")){
                currentArticle = new ArrayList<Node>();
                articles.add(currentArticle);
            }

            currentArticle.add(node);
        }

        for(List<Node> article : articles){
            for(Node node : article){
                System.out.println(node);
            }
            System.out.println("------- new page ---------");
        }

    }

}

你知道文章的结构吗?它们总是相同的吗?你想对这些文章做什么?你考虑过在客户端将它们拆分吗?这将是一个简单的jQuery工作。


编辑:更改元素为节点,以更通用地捕获不带周围标记的文本节点。 - Tim Büthe
没有结构一定不一样。实际上这些都是转换为过滤后的 HTML 的 Word 文档。 - Sunil Ramu

2

在连续的 <h> 元素之间迭代似乎是没问题的,但有一个例外情况。不属于任何标签的文本,比如在 <h1/>this<h1/> 中。为了解决这个问题,我实现了 splitElemText 函数来获取这段文本。首先使用该方法拆分整个父元素。接着在处理适当的拆分文本条目时除去元素。如果想要原始的HTML,请删除对 htmlToText 的调用。

/** Splits the text of the element <code>elem</code> by the children
  * tags.
  * @return An array of size <code>c+1</code>, where <copde>c</code>
  * is the number of child elements.
  * <p>Text after <code>n</code>th element is found in <code>[n+1]</code>.
  */
public static String[] splitElemText(Element elem)
{
  int c = elem.children().size();
  String as[] = new String[c + 1];
  String sAll = elem.html();
  int iBeg = 0;
  int iChild = 0;
  for (Element ch : elem.children()) {
    String sChild = ch.outerHtml();
    int iEnd = sAll.indexOf(sChild, iBeg);
    if (iEnd < 0) { throw new RuntimeException("Tag " + sChild
                    +" not found in its parent: " + sAll);
    }
    as[iChild] = htmlToText(sAll.substring(iBeg, iEnd));
    iBeg = iEnd + sChild.length();
    iChild += 1;
  }
  as[iChild] = htmlToText(sAll.substring(iBeg));
  assert(iChild == c);
  return as;
}

public static String htmlToText(String sHtml)
{
  Document doc = Jsoup.parse(sHtml);
  return doc.text();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接