Jsoup è parser HTML5 (conforme alle specifiche WHATWG) le cui API consentono di estrarre dati e manipolare in maniera estremamente semplice documenti sfruttando le potenzialità di DOM, CSS e metodi di accesso simili a quelli offerti da JQuery.
Accedere a documenti HTML
In Jsoup un documento xml è rappresentato dalla classe Document
, i nodi del documento da istanze della classe Node
e i tag da istanze della classe Element
Esistono tre diversi modi per effettuare il parsing di un documento xml ed ottenere così un Document che lo rappresenti:
- caricare il documento da un URL
- caricare il documento da un File
- effettuare il parsing di una String rappresentante il contenuto del documento xml o una parte di questo
Nel primo caso si utilizza il metodo connect della classe Jsoup:
Document doc = Jsoup.connect("http://html.it/").get();
Nel secondo caso si utilizza il metodo parse della classe Jsoup passando come argomenti il File di input, il charset e il base-uri con il quale risolvere gli indirizzi relativi:
File input = new File("documento.html");
Document doc = Jsoup.parse(input, "UTF-8", "http://html.it/");
Nel terzo caso si utilizza il metodo parse della classe Jsoup passando una String rappresentante il contenuto del documento, e il base-uri:
String html = "<html> <head> <title> Documento di prova </title> </head> <body> Corpo del body </body> </html>";
Document doc = Jsoup.parse(html, "http://html.it/");
E' possibile effettuare anche il parsing di un frammento di codice HTML mediante il metodo parseBodyFragment
:
String html = "<div> DIV inserito </div>";
Document doc = Jsoup.parseBodyFragment(html);
Element body = doc.body();
quest'ultimo metodo risulta particolarmente interessante quando si ha la necessità di navigare una parte dell'interno albero HTML senza voler tuttavia caricare tutto il documento all'interno della memoria.
Navigare un documento HTML
Una volta ottenuta l'istanza della classe Document
è possibile procedere alla navigazione del documento sfruttando diversi metodi.
Supponiamo di utilizzare il seguente codice HTML:
<html>
<head>
<title>
Documento HTML di prova
</title>
</head>
<body>
<div> div 1 </div>
<div id="div_2"> div 2 </div>
<div> div 3 </div>
</body>
</html>
E di aver effettuato il parsing del documento HTML in uno dei modi che abbiamo precedentemente illustrato.
A questo punto, per accedere al title del documento si utilizza il metodo title()
del Document
, per cui:
System.out.println(document.title());
Produce in output:
Documento HTML di prova
Per accedere al body del documento, si usa invece il metodo body()
dell'oggetto Document
a partire dal quale è possibile procedere con la navigazione del documento.
In particolare:
per recuperare l'elemento-figlio i-esimo di un altro si usa il metodo child(int index):
Element figlio = document.body().child(0);
per recuperare l'elemento adiacente successivo o precedente ad un dato elemento si usano i metodi nextElementSibling()
e previousElementSibling()
per cui, se volessimo stampare tutti gli elementi di pari livello di un dato Element
:
Element primo_figlio = documento.body().child(0);
while (primo_figlio.nextElementSibling()!=null)
{
System.out.println(primo_figlio);
primo_figlio = primo_figlio.nextElementSibling();
}
System.out.println(primo_figlio);
Per recuperare tutti gli elementi di un dato tag si usa getElementsByTag()
passando come argomento il tag desiderato:
Elements elementi_div = document.getElementsByTag(“div”);
come risultato si ottiene un oggetto Elements
che rappresenta una collezione di Element
(tanti quanti sono gli elementi con dato tag presenti all'interno del documento).
per recuperare un elemento a partire dall'id si usa il metodo getElementById()
passando come argomento l'id desiderato:
Element div2 = document.getElementById(“div_2”);
Jsoup mette a disposizione anche due metodi per recuperare elementi che abbiano un dato attributo (a prescindere dal valore)
Elements elementi = documento.body().getElementsByAttribute("id");
for (Element elemento: elementi)
System.out.println(elemento);
o che abbiamo un dato attributo valorizzato in un modo ben preciso:
Elements elementi = documento.body().getElementsByAttributeValue("id",”div_2”);
for (Element elemento: elementi)
System.out.println(elemento);
Per recuperare l'Element
padre di un dato Element
si usa il metodo parent()
:
Element padre = figlio.parent();
Questi sono i principali modi per accedere agli Element
presenti all'interno di un Document
.
Se si vuole accedere agli attributi di un Element
si usano invece i metodi:
attributes()
: recupera tutti gli attributi di un Element restituendo un oggetto Attributes che è una collection di Attribute
Attributes attributi = element.attributes();
attr()
: recupera l'attributo il cui nome è passato come argomento:
Attribute attributo = element.attr(“id”);
Utilizzo dei selettori
Accanto ai metodi tradizionali per l'accesso agli elementi di un documento html, Jsoup introduce uno strumento molto potente per recuperare uno o più elementi attraverso l'uso di selettori.
Un selettore è un'espressione che individua un sottoinsieme degli elementi presenti in un documento.
Una volta definito il selettore è possibile utilizzare il metodo select(String selettore)
di un Element
per selezionare gli elementi individuati dal selettore ottenendo come risultato una collection Elements
.
Il selettore viene costruito considerando che:
"nometag"
: recupera tutti gli elementi che hanno il tag nometag
body.select(“div”)
"#id"
: recupera l'elemento che ha il dato id
body.select(“#div_2”);
".nomeclasse"
: recupera gli elementi che hanno come classe css nome classe
body.select(“.rosso”);
"[nome attributo]"
: recupera gli elementi che hanno l'attributo specificato
body.select(”[id]”)
"[nome_attributo=valore_attributo]"
: recupera gli elementi che hanno per l'attributo indicato il valore indicato
Body.select(“[id=div_2]”);
Ovviamente è possibile utilizzare un selettore composto da una o più delle precedenti regole.
Ad esempio supponendo di voler recuperare tutti gli elementi con tag div e classe css rosso, utilizzeremo il selettore:
“div.rosso”
Modifica dei contenuti di un documento HTML
Accanto ai metodi per selezionare e navigare gli elementi di un documento xml Jsoup mette a disposizione un insieme di metodi per manipolarne il contenuto.
html(String html)
: modifica l'Element
sostituendolo con il codice passato come argomento.
element.html(“<p>paragrafo</p>”);
prepend(String html)
: aggiunge l'Element
di cui viene passato il codice in testa agli elementi figlio dell'elemento dato
element.prepend(“<p>paragrafo iniziale</p>”);
append(String html)
: aggiunge l'Element
di cui viene passato il codice in coda agli elementi figlio dell'elemento dato
element.append(“<p>paragrafo finale</p>”);
Per modificare gli attributi di un Element
si usa invece il metodo:
element.attr(“class”,”rosso”);
e poi?
Ovviamente lo scopo di questa brevissima introduzione era soltanto quello di offrire una idea generale delle possibilità di utilizzo di questa libreria, le cui possibilità di utilizzo possono spaziare dai consueti contesti web a contesti meno ovvi, come la produzione di pdf/ebook, ad esempio, grazie ad una modalità di programmazione molto intuitiva.