BigThink

Java: parsing di una pagina HTML

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.

Articolo scritto da Ghido

Fondatore di BigThink.it, si occupa dello sviluppo e del coordinamento dei progetti tecnologici. Specializzato nel Marketing su Facebook e nello sviluppo di Applicazioni Social, fa consulenza e formazione ad aziende ed agenzie.

Leggi anche...

PasteQuestion.com: aiuto gratis dagli esperti di programmazione

PasteQuestion.com: aiuto gratis dagli esperti di programmazione

Quante volte vi siete trovati in difficoltà, programmando un'applicazione o un sito web, e siete andati alla disperata ricerca della soluzione su Google? Quante volte vi siete fiondati sui forum di programmazione, sperando in un aiuto dai più esperti? Quante volte siete approdati su BigThink, chiedendomi aiuto per sistemare il vostro template o plugin WordPress ...
TDD con java: Fibonacci

TDD con java: Fibonacci

Un paio di post fa ho parlato di Test Driven Development, sviluppare software scrivendo prima i test e poi il codice. Vi consiglio di leggerlo, prima di dedicarvi a questo. Quest'oggi vi riporto un esempio per chiarirvi meglio le idee, tratto dal libro Test Driven Development by Example di Kent Beck: scriviamo un metodo ...
Test Driven Development: prima i test, poi il codice

Test Driven Development: prima i test, poi il codice

Un metodo non tradizionale e agile per lo sviluppo e il design del software è il Test Driven Development (TDD): sviluppo guidato dai test. E' un'alternativa al solito metodo a cascata (waterfall), secondo il quale, dopo un'adeguata analisi e progettazione, si inizia a scrivere il codice e solo alla fine si passa al ...

8 Commenti

  1. 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?

    31 agosto 2010, 20:33
  2. Davide

    Ciao

    a me nodes mi da valore 0 e quindi non visualizza niente cosa può essere?

    grazie

    15 aprile 2010, 12:47
  3. Antonio

    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?

    22 gennaio 2010, 22:44
  4. strad84

    e se non volessi usare Jtidy ? al posto di response qui

    NodeList nodes = (NodeList)xPath.evaluate(pattern, response, XPathConstants.NODESET);

    cosa dovrei mettere? grazie

    21 agosto 2009, 11:52
  5. Ghido

    [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.

    26 settembre 2008, 16:01
  6. Umberto

    a me non funziona, gli do in input un file .html per trasformarlo in xml si blocca sugli javascript. Che si fa?

    26 settembre 2008, 15:36

2 Citazioni