Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用jsoup解析HTML表?_Java_Html_Parsing_Jsoup - Fatal编程技术网

Java 如何使用jsoup解析HTML表?

Java 如何使用jsoup解析HTML表?,java,html,parsing,jsoup,Java,Html,Parsing,Jsoup,我正在尝试使用jsoup解析HTML。这是我第一次使用jsoup,我也读了一些关于它的教程。下面是我试图解析的HTML表- 如果您看到我的下表,那么到目前为止,它有三个tr(为了理解,我将它缩短为三个表行,但通常会更多)。现在,我想从下表中提取集群名称,它对应的主机名,例如,我将提取Titan作为集群名称及其状态为down的所有主机名 正如您在下面看到的Titan集群名称一样,我有两个主机名machineA.abc.com和machineB.abc.com,其中machineA状态为up,但ma

我正在尝试使用jsoup解析HTML。这是我第一次使用jsoup,我也读了一些关于它的教程。下面是我试图解析的HTML表-

如果您看到我的下表,那么到目前为止,它有三个
tr
(为了理解,我将它缩短为三个表行,但通常会更多)。现在,我想从下表中提取
集群名称
,它对应的
主机名
,例如,我将提取
Titan
作为集群名称及其状态为down的所有主机名

正如您在下面看到的
Titan
集群名称一样,我有两个主机名
machineA.abc.com
machineB.abc.com
,其中
machineA
状态为
up
,但
machineB
状态为
down

因此,我将打印出
Titan
作为集群名称,并打印出
machineB.abc.com
作为主机名,因为它已关闭。使用jsoup可以做到这一点吗

<table border=1>
   <tr>
      <td>&nbsp;</td>
      <td>&nbsp;</td>
      <td>Alert</td>
      <td>Cluster Name</td>
      <td>IP addr</td>
      <td>Host Name</td>
      <td>Type</td>
      <td>Status</td>
      <td>Free</td>
      <td>Version</td>
      <td>Restart Time</td>
      <td>UpTime(Days)</td>
      <td>Last probed</td>
      <td>Last up</td>
   </tr>
   <tr bgcolor="ffffff">
      <td><a href=showlog?ip_addr=127.0.0.1>Hist</a></td>
      <td><a href=http://127.0.0.1:8080/test?full=y>VI</a></td>
      <td bgcolor="ffffff">&nbsp</td>
      <td>Titan</td>
      <td>10.100.111.77</td>
      <td>machineA.abc.com</td>
      <td></td>
      <td bgcolor="ffffff">up</td>
      <td bgcolor="ffffff" align=right>88%</td>
      <td bgcolor="ffffff">2.0.5-SNAPSHOT</td>
      <td bgcolor="ffffff">2014-07-04 01:49:08,220</td>
      <td bgcolor="ffffff" align=right>381</td>
      <td>07-14 20:01:59</td>
      <td>07-14 20:01:59</td>
   </tr>
   <tr bgcolor="ffffff">
      <td><a href=showlog?ip_addr=127.0.0.1>Hist</a></td>
      <td><a href=http://127.0.0.1:8080/test?full=y>VI</a></td>
      <td bgcolor="ffffff">&nbsp</td>
      <td></td>
      <td>10.200.192.99</td>
      <td>machineB.abc.com</td>
      <td></td>
      <td bgcolor="ffffff">down</td>
      <td bgcolor="ffffff" align=right>85%</td>
      <td bgcolor="ffffff">2.0.5-SNAPSHOT</td>
      <td bgcolor="ffffff">2014-07-04 01:52:20,613</td>
      <td bgcolor="ffffff" align=right>103</td>
      <td>07-14 20:01:59</td>
      <td>07-14 20:01:59</td>
   </tr>
</table>
更新:-

表中可能有两个集群名称,如下所示-

<table border=1>
   <tr>
      <td>&nbsp;</td>
      <td>&nbsp;</td>
      <td>Alert</td>
      <td>Cluster Name</td>
      <td>IP addr</td>
      <td>Host Name</td>
      <td>Type</td>
      <td>Status</td>
      <td>Free</td>
      <td>Version</td>
      <td>Restart Time</td>
      <td>UpTime(Days)</td>
      <td>Last probed</td>
      <td>Last up</td>
   </tr>
   <tr bgcolor="ffffff">
      <td><a href=showlog?ip_addr=127.0.0.1>Hist</a></td>
      <td><a href=http://127.0.0.1:8080/test?full=y>VI</a></td>
      <td bgcolor="ffffff">&nbsp</td>
      <td>Titan</td>
      <td>10.100.111.77</td>
      <td>machineA.abc.com</td>
      <td></td>
      <td bgcolor="ffffff">up</td>
      <td bgcolor="ffffff" align=right>88%</td>
      <td bgcolor="ffffff">2.0.5-SNAPSHOT</td>
      <td bgcolor="ffffff">2014-07-04 01:49:08,220</td>
      <td bgcolor="ffffff" align=right>381</td>
      <td>07-14 20:01:59</td>
      <td>07-14 20:01:59</td>
   </tr>
   <tr bgcolor="ffffff">
      <td><a href=showlog?ip_addr=127.0.0.1>Hist</a></td>
      <td><a href=http://127.0.0.1:8080/test?full=y>VI</a></td>
      <td bgcolor="ffffff">&nbsp</td>
      <td></td>
      <td>10.200.192.99</td>
      <td>machineB.abc.com</td>
      <td></td>
      <td bgcolor="ffffff">down</td>
      <td bgcolor="ffffff" align=right>85%</td>
      <td bgcolor="ffffff">2.0.5-SNAPSHOT</td>
      <td bgcolor="ffffff">2014-07-04 01:52:20,613</td>
      <td bgcolor="ffffff" align=right>103</td>
      <td>07-14 20:01:59</td>
      <td>07-14 20:01:59</td>
   </tr>
   <tr bgcolor="ffffff">
      <td><a href=showlog?ip_addr=127.0.0.1>Hist</a></td>
      <td><a href=http://127.0.0.1:8080/test?full=y>VI</a></td>
      <td bgcolor="ffffff">&nbsp</td>
      <td>Goldy</td>
      <td>10.100.111.77</td>
      <td>machineH.pqr.com</td>
      <td></td>
      <td bgcolor="ffffff">up</td>
      <td bgcolor="ffffff" align=right>88%</td>
      <td bgcolor="ffffff">2.0.5-SNAPSHOT</td>
      <td bgcolor="ffffff">2014-07-04 01:49:08,220</td>
      <td bgcolor="ffffff" align=right>381</td>
      <td>07-14 20:01:59</td>
      <td>07-14 20:01:59</td>
   </tr>       
</table>

警觉的
群集名称
IP地址
主机名
类型
地位
自由的
版本
重新启动时间
正常运行时间(天)
最后探测
最后
 
泰坦
10.100.111.77
machineA.abc.com
向上的
88%
2.0.5-快照
2014-07-04 01:49:08,220
381
07-14 20:01:59
07-14 20:01:59
 
10.200.192.99
machineB.abc.com
向下
85%
2.0.5-快照
2014-07-04 01:52:20,613
103
07-14 20:01:59
07-14 20:01:59
 
金色的
10.100.111.77
machineH.pqr.com
向上的
88%
2.0.5-快照
2014-07-04 01:49:08,220
381
07-14 20:01:59
07-14 20:01:59

现在,如果你看到上面我有两个集群名称-一个是
Titan
,另一个是
Goldy
,所以我只想找到
Titan
集群名称下的所有机器。

在你的情况下,我要做的是首先创建一个具有所有适当属性的机器对象。然后使用Jsoup提取数据并创建ArrayList,然后使用逻辑从ArrayList获取数据

我将跳过对象创建(因为这不是这里的问题),并将对象命名为
Machine

然后使用Jsoup,我将获得如下行数据:

ArrayList<Machine> list = new ArrayList();
Document doc = Jsoup.parse(url, 3000);
for (Element table : doc.select("table")) { //this will work if your doc contains only one table element
  for (Element row : table.select("tr")) {
    Machine tmp = new Machine();
    Elements tds = row.select("td");
    tmp.setClusterName(tds.get(3).text());
    tmp.setIp(tds.get(4).text());
    tmp.setStatus(tds.get(7).text());
    //.... and so on for the rest of attributes
    list.add(tmp);
  }
}

就这些。还请注意,此代码未经测试,可能包含一些语法错误,因为它是直接在此编辑器上编写的,而不是在IDE中编写的

是的,使用JSoup是可能的。首先,选择表。然后,为行选择
标记。您可以从第二个索引开始,因为第一行只包含列名。然后循环遍历
标记并获得特定索引。在您的例子中,索引7和5很重要(索引7:状态,索引5:主机名)。检查状态是否等于
down
,如果是,则将主机名添加到列表中。就这些

ArrayList<String> downServers = new ArrayList<>();
Element table = doc.select("table").get(0); //select the first table.
Elements rows = table.select("tr");

for (int i = 1; i < rows.size(); i++) { //first row is the col names so skip it.
    Element row = rows.get(i);
    Elements cols = row.select("td");

    if (cols.get(7).text().equals("down")) {
        downServers.add(cols.get(5).text());
    }
}

downServers ArrayList将包含宕机服务器主机名列表。

下面是一个干净的通用函数,用于将html表提取到简单的列表映射结构中

将文档以表格顺序传递给此函数,要求在html页面中输入第n个表格

如果表使用rowspan或colspan,函数将不会返回准确的数据

public static List<Map<String,String>> parseTable(Document doc, int tableOrder) {
    Element table = doc.select("table").get(tableOrder);
    Elements rows = table.select("tr");
    Elements first = rows.get(0).select("th,td");

    List<String> headers = new ArrayList<String>();
    for(Element header : first)
        headers.add(header.text());

    List<Map<String,String>> listMap = new ArrayList<Map<String,String>>();
    for(int row=1;row<rows.size();row++) {
        Elements colVals = rows.get(row).select("th,td");
        //check column size here

        int colCount = 0;
        Map<String,String> tuple = new HashMap<String,String>();
        for(Element colVal : colVals)
            tuple.put(headers.get(colCount++), colVal.text());
        System.out.println(tuple.toString());
        listMap.add(tuple);
    }
    return listMap;
}
公共静态列表解析表(Document doc,int tableOrder){
元素表=doc.select(“表”).get(tableOrder);
元素行=表。选择(“tr”);
元素优先=行。获取(0)。选择(“th,td”);
列表标题=新建ArrayList();
for(元素标题:第一个)
headers.add(header.text());
List listMap=new ArrayList();

对于(int row=1;rowYup)它可以正常工作。但是有一个问题。我刚刚更新了这个问题。我只需要找出
Titan
集群名称的停止服务器。这也可能吗?是的,您可以更改if条件。if(cols.get(7.text().equals(“down”)和&cols.get(3.text().equals(“Titan”))不知何故,它不起作用,因为群集名称不在每一行中,只是第一次出现,然后是与该群集相关的主机名。然后是另一个群集名称,后面是它的主机名。请参阅更新,我无法测试它,但我认为它对您的情况有效。我只是尝试了一下,但不知何故它不起作用。知道会出什么问题吗?Th不考虑第一行是标题,所以使用:只是对任何人使用HTML片段的一个旁注:JSoup不能够解析<代码> <代码>而没有<代码> <代码>。最简单的解决方案是在解析代码之前用<代码> <代码>包装字符串。
ArrayList<String> downServers = new ArrayList<>();
Element table = doc.select("table").get(0); //select the first table.
Elements rows = table.select("tr");

for (int i = 1; i < rows.size(); i++) { //first row is the col names so skip it.
    Element row = rows.get(i);
    Elements cols = row.select("td");

    if (cols.get(7).text().equals("down")) {
        downServers.add(cols.get(5).text());
    }
}
    ArrayList<String> downServers = new ArrayList<>();
    Element table = doc.select("table").get(0); //select the first table.
    Elements rows = table.select("tr");

    for (int i = 1; i < rows.size(); i++) { //first row is the col names so skip it.
        Element row = rows.get(i);
        Elements cols = row.select("td");

        if (cols.get(3).text().equals("Titan")) {
            if (cols.get(7).text().equals("down"))
                downServers.add(cols.get(5).text());

            do {
                if(i < rows.size() - 1)
                   i++;
                row = rows.get(i);
                cols = row.select("td");
                if (cols.get(7).text().equals("down") && cols.get(3).text().equals("")) {
                    downServers.add(cols.get(5).text());
                }
                if(i == rows.size() - 1)
                    break;
            }
            while (cols.get(3).text().equals(""));
            i--; //if there is two Titan names consecutively.
        }
    }
public static List<Map<String,String>> parseTable(Document doc, int tableOrder) {
    Element table = doc.select("table").get(tableOrder);
    Elements rows = table.select("tr");
    Elements first = rows.get(0).select("th,td");

    List<String> headers = new ArrayList<String>();
    for(Element header : first)
        headers.add(header.text());

    List<Map<String,String>> listMap = new ArrayList<Map<String,String>>();
    for(int row=1;row<rows.size();row++) {
        Elements colVals = rows.get(row).select("th,td");
        //check column size here

        int colCount = 0;
        Map<String,String> tuple = new HashMap<String,String>();
        for(Element colVal : colVals)
            tuple.put(headers.get(colCount++), colVal.text());
        System.out.println(tuple.toString());
        listMap.add(tuple);
    }
    return listMap;
}