Nella nostra carriera di programmatori, potrà capitarci di dover effettuare la lettura di dati da una pagina web: magari dobbiamo implementare uno spider per la ricerca di determinati link in una pagina, piuttosto che per raccogliere email o qualsiasi altra cosa che ci può essere utile estrapolare da una pagina HTML, in modo automatico.
Java integra una serie di librerie e classi per il parsing di un documento XML, ma che si applicano solamente a documenti ben formati. La maggior parte delle volte, invece, le pagine HTML non rispettano gli standard W3C e sono piene di errori come tag non chiusi o annidati in modo errato. Per questo motivo, se cercheremo di trattare una pagina HTML come un file XML, non riusciremo a cavarne niente.
Tuttavia, esistono online numerose librerie che eseguono per noi questo sporco compito: “aggiustare” una pagina HTML, corregendone gli errori e trasformandola in un file XML valido, ben formato e leggibile. La libreria che vi propongo è JTidy. Una volta scaricata, importatela nel vostro progetto Java e vediamo come usarla.
Per prima cosa leggiamo la pagina che ci interessa:
1 2 | URL url = new URL("http://www.paginadaleggere.com"); BufferedInputStream page = new BufferedInputStream(url.openStream()); |
Quindi ripuliamola con JTidy:
3 4 5 6 | Tidy tidy = new Tidy(); tidy.setQuiet(true); tidy.setShowWarnings(false); Document response = tidy.parseDOM(page, null); |
Ora utilizziamo l’oggetto XPath per andare a recuperare i nodi che ci interessano:
7 8 9 10 | XPathFactory factory = XPathFactory.newInstance(); XPath xPath=factory.newXPath(); String pattern = "//body/a"; NodeList nodes = (NodeList)xPath.evaluate(pattern, response, XPathConstants.NODESET); |
Per navigare all’interno del nostro albero, si utilizza un comodissimo linguaggio chiamato XML Path Language, XPath appunto, che ci permette di specificare con precisione quali elementi vogliamo.
Se volessimo recuperare, ad esempio, tutti i titoli presenti in un determinato div con id “main”, ci basterà impostare come pattern la stringa:
//div[@id='main']/h1/text()
Se invece abbiamo bisogno di tutti gli url presenti nella pagina che hanno class “link”, scriveremo:
//a[@class='link']/@href
Fatto ciò, ci verrà restituito un oggetto di tipo NodeList, che andremo ad utilizzare, iterando su ogni elemento:
11 12 13 | for (int i = 0; i < nodes.getLength(); i++) { System.out.println((String) nodes.item(i).getNodeValue()); } |
Questo è tutto. Poi potrete usare gli elementi come meglio credete.




Ciao, ottimo articolo, però ho un problema e non so se l’hai riscontrato. quando seleziono text() da un div, se all’interno c’è un tag html, tipo , questo non lo estrae. hai qualche idea?
ecco vabbè… era il tag
uffa… tag bold, facciamo prima
Ciao
a me nodes mi da valore 0 e quindi non visualizza niente cosa può essere?
grazie
Ciao,
il tuo articolo mi ha aiutato molto ma ora sono arrivatoa d un punto morto. Se leggo un node set come faccio ad estrarre tutti i testi contenuti in tutti i nodi e sottonodi figli?
e se non volessi usare Jtidy ? al posto di response qui
NodeList nodes = (NodeList)xPath.evaluate(pattern, response, XPathConstants.NODESET);
cosa dovrei mettere? grazie
[Comment ID #740 Will Be Quoted Here]
Mmm… brutto affare i javascript…
Secondo me se funzionerebbe se fosse scritto in XHTML corretto. Ovvero con la sintassi:
<script type="text/javascript">
<![CDATA[
//resto del codice
]]>
</script>
Prova a fare un replace, prima di parsarlo.
a me non funziona, gli do in input un file .html per trasformarlo in xml si blocca sugli javascript. Che si fa?