Как анализировать таблицу HTML с помощью jsoup?
Я пытаюсь разобрать HTML с помощью jsoup. Это мой первый опыт работы с jsoup, и я также прочитал его. Ниже моя таблица HTML, которую я пытаюсь разобрать -
Если вы видите мою нижнюю таблицу, она имеет три tr
на данный момент (я сократил ее, чтобы иметь три строки таблицы только для понимания цели, но в целом это будет больше). Теперь я хотел бы извлечь Cluster Name
из моей таблицы ниже, и это соответствует host name
так, например, - я бы извлек Titan
в качестве имени кластера и все его имя хоста, статус которого опущен.
Как вы можете видеть ниже для названия кластера Titan
, у меня есть два имени хоста machineA.abc.com
и machineB.abc.com
, в которых machineA
статус up
, а machineB
статус down
.
Итак, я напечатаю Titan
как имя кластера и распечатаю machineB.abc.com
как имя хоста, так как он не работает. Можно ли это сделать с помощью jsoup?
<table border=1>
<tr>
<td> </td>
<td> </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"> </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"> </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>
До сих пор я могу извлечь всю таблицу HTML с помощью jsoup, но не уверен, как извлечь из нее имя кластера и имена хостов, которые опущены -
URL url = new URL("url_name");
Document doc = Jsoup.parse(url, 3000);
Обновление: -
В таблице может быть два имени кластера, как показано ниже -
<table border=1>
<tr>
<td> </td>
<td> </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"> </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"> </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"> </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>
Теперь, если вы видите выше, у меня есть два имени кластера: один - Titan
, а другой - Goldy
, поэтому я хочу найти все машины, для которых указано только имя кластера Titan
.
Ответы
Ответ 1
Да, это возможно с JSoup. Сначала вы выбираете таблицу. Затем вы выбираете теги <tr>
для строк. Вы можете начать со второго индекса, так как первая строка содержит только имена столбцов. Затем переместите теги <th>
и получите конкретный индекс. В вашем случае индексы 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());
}
}
Update:
Когда вы найдете слово Titan
, вы можете создать еще один цикл и посмотреть, пустое ли имя кластера.
Изменить: Я меняю цикл while
на цикл do while
.
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.
}
}
downServers ArrayList будет содержать список имен хостов down-серверов.
Ответ 2
Что бы я делал в вашем случае, сначала создайте Object своей машины со всеми подходящими атрибутами. Затем, используя Jsoup, я бы извлек данные и создал ArrayList, а затем использовал логику для получения данных от Arraylist.
Я пропускаю создание объекта (так как это не проблема), и я назову Object как 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);
}
}
Затем используйте цикл, чтобы получить нужные значения из списка:
for(Machine x:list){
if(x.getStatus().equalsIgnoreCase("up")){
//machine with UP status found
System.out.println("The Machine with up status is:"+x.getHostName());
}
}
Это все. Также обратите внимание, что этот код не проверен и может содержать некоторые синтаксические ошибки, поскольку он написан непосредственно в этом редакторе, а не в среде IDE.