【问题标题】:Jsoup: How to get all html between 2 header tagsJsoup:如何获取 2 个标头标签之间的所有 html
【发布时间】:2011-09-25 22:35:33
【问题描述】:

我正在尝试获取 2 个 h1 标签之间的所有 html。实际任务是根据 h1(heading 1) 标签将 html 分解为帧(章节)。

感谢任何帮助。

谢谢 苏尼尔

【问题讨论】:

  • 你想从中获取'

    abc

    ' abc
  • 我想他想把所有内容都拿到下一个h1,这样他就可以按标题拆分页面了。

标签: java jsoup


【解决方案1】:

如果您想获取和处理两个连续的h1 标签之间的所有元素,您可以使用兄弟姐妹。下面是一些示例代码:

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 上查找更多示例。
  • 我假设您要打印标题文本而不是其名称(H1 标题的名称始终为“H1”)。因此,要做到这一点,您只需在调用processElementsBetween(elementsBetween); 之前打印sibling.ownText()。我不确定您所说的“让标题按顺序排列”是什么意思。 JSoup 文档:cookbookapidocs
  • 这不适用于不属于标签的文本,例如&lt;h1/&gt;this&lt;h1/&gt;。这似乎是 jsoup 概念中的一个漏洞。
【解决方案2】:

我不太了解 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 作业。

【讨论】:

  • 编辑:将元素更改为节点,使其更通用并捕获文本 nodex 而无需周围的标签。
  • 没有结构并不总是相同的。实际上,这些都是转换为过滤 HTML 的 word 文档。
【解决方案3】:

迭代连续的&lt;h&gt; 元素之间的元素似乎很好,除了一件事。不属于任何标签的文本,例如&lt;h1/&gt;this&lt;h1/&gt;。为了解决这个问题,我实现了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();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-26
    • 2015-07-07
    相关资源
    最近更新 更多