我是jsoup的新手,可能使用它错了。我打算联系邮件列表,但是jsoup instructs to post here first。我试图从表中选择<td>
元素,但返回的第一个元素实际上是<thead>
。这是获取给定表的<td>
元素的错误方法吗?如果是这样,那么正确的方法是什么?
以下简单代表性问题:
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
答案 0 :(得分:2)
据推测,jsoup在解析HTML文档时会将<th>
元素放在自己的<tr>
中,从而产生以下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选择器来获取<tbody>
中的行:
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()
会更加清晰。)
如果您不需要先浏览行,只想直接获取<td>
元素,则可以这样做:
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");