【问题标题】:jsoup returning <thead> tags when <tr> tags are selected?选择 <tr> 标签时,jsoup 返回 <thead> 标签?
【发布时间】:2015-06-03 01:07:15
【问题描述】:

我是 jsoup 的新手,可能用错了。我打算联系邮件列表,但 jsoup instructs to post here first。我正在尝试从表中选择&lt;td&gt; 元素,但返回的第一个元素实际上是&lt;thead&gt;。这是获取给定表的&lt;td&gt; 元素的错误方法吗?如果是这样,正确的方法是什么?

下面的简单代表性问题:

HTML:

<table id="results_table">
    <thead>
        <th>Header1</th>
    </thead>
    <tbody>
        <tr>
            <td>td1</td>
        </tr>
    </tbody>
</table>

测试:

String pageHtml = IOUtils.toString(this.getClass().getResourceAsStream("sample.html"));
Document doc = Jsoup.parse(pageHtml);
Element table = doc.getElementById("results_table");
Elements trs = table.getElementsByTag("tr");

System.out.println("Size: " + trs.size());
System.out.println("First Element: " + trs.get(0).html());
System.out.println("Second Element: " + trs.get(1).html());

收到的输出:

Size: 2
First Element: <th>Header1</th>
Second Element: <td>td1</td>

预期输出:

Size: 1
First Element: <td>td1</td>
//Index out of bounds exception

【问题讨论】:

    标签: html jsoup


    【解决方案1】:

    大概是jsoup在解析HTML文档的时候把&lt;th&gt;元素放到了自己的&lt;tr&gt;里面,导致了下面的DOM:

    <table id="results_table">
        <thead>
            <tr>
                <th>Header1</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>td1</td>
            </tr>
        </tbody>
    </table>
    

    由于表格单元格必须位于表格行中(这意味着您的源 HTML 文件无效),我希望任何 HTML 处理器,尤其是 Web 浏览器,都可以这样做(虽然在 XML 模式下不会发生这种情况, jsoup 不支持)。

    相反,您可以将 doc.select() 与 CSS 选择器一起使用,以仅获取 &lt;tbody&gt; 中的行:

    String pageHtml = IOUtils.toString(this.getClass().getResourceAsStream("sample.html"));
    Document doc = Jsoup.parse(pageHtml);
    Elements trs = doc.select("#results_table tbody tr");
    
    System.out.println("Size: " + trs.size());
    System.out.println("First Element: " + trs.get(0).html());
    System.out.println("Second Element: " + trs.get(1).html()); // IndexOutOfBoundsException
    

    (您也可以使用一系列getElementsByTag() 调用,但这需要额外的遍历和迭代;使用doc.select() 更简洁。)

    如果您不需要先遍历行而只是想直接获取&lt;td&gt; 元素,则可以这样做:

    String pageHtml = IOUtils.toString(this.getClass().getResourceAsStream("sample.html"));
    Document doc = Jsoup.parse(pageHtml);
    Element table = doc.getElementById("results_table");
    Elements tds = table.getElementsByTag("td");
    

    【讨论】:

    • 在这一点上感觉很愚蠢。我没有意识到我正在抓取的页面是无效的 html。为“愚蠢”的问题道歉,并欣赏有价值的深入回答。我将不得不学习更多关于 CSS 选择器方法的知识,因为它肯定会让我更有表现力(并解决我手头的问题)。谢谢,再次抱歉没有意识到它是无效的 html。
    • @Russ:没关系,网站并不完全以符合标准而著称,因此您可能会发现自己经常处理无效的 HTML :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-04
    • 1970-01-01
    • 1970-01-01
    • 2014-05-09
    • 1970-01-01
    相关资源
    最近更新 更多