mercoledì 15 ottobre 2008

Grails e HtmlUnit

Nei giorni scorsi ho provato a fare qualche prova di web screen-scraping in un progetto Grails, utilizzando HtmlUnit 2.3.
Dopo aver creato una applicazione Grails di prova e aver messo tutti i jar della distribuzione di HtmlUnit nella cartella lib, ho provato a lanciare l'applicazione...ottenendo come risultato solo questa bella eccezione:

Error executing script RunApp: Class org.apache.xerces.parsers.AbstractSAXParser$AttributesProxy does not implement the requested interface org.xml.sax.Attributes
java.lang.IncompatibleClassChangeError: Class org.apache.xerces.parsers.AbstractSAXParser$AttributesProxy does not implement the requested interface o
rg.xml.sax.Attributes
at groovy.util.XmlSlurper.startElement(XmlSlurper.java:305)
...

Dopo qualche ricerca e qualche tentativo ho scoperto che il problema si risolve cancellando il jar xml-apis-1.0.b2.jar dalla directory lib.

Una volta avviato il server ho potuto testare la connessione ad un sito qualunque, (http://www.daviderossi.org/ ;-) ), creando una nuova action nel controller e stampando sulla console il risultato.

Prima di poter accedere al sito, ho però dovuto configurare un proxy, in questo modo:

WebClient webClient = new WebClient(BrowserVersion.FIREFOX_2, "proxy.it", 8080)
((DefaultCredentialsProvider) webClient.getCredentialsProvider()).addProxyCredentials("user", "password");

Le possibilità offerte da HtmlUnit sono moltissime, tra cui la possibilità di trovare gli elementi per nome, id o attraverso un percorso xpath, cosi come inviare form o cliccare link...
Il primo test che ho fatto è stato di collegarmi alla home page, individuare il link alla pagina 'Tecnologie', cliccarlo e leggere il contenuto della pagina come testo.
Il codice completo della action e' questo:

def provaHome = {
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_2, "proxy.it", 8080)

(DefaultCredentialsProvider)webClient.getCredentialsProvider()).addProxyCredentials("user", "password");
HtmlPage homePage = (HtmlPage) webClient.getPage('http://www.daviderossi.org/')
println homePage.getTitleText()
def xpath = "//a[.='Tecnologie']"
def link = homePage.getByXPath(xpath)?.get(0)
HtmlPage resultPage = (HtmlPage) link.click()
def content = resultPage.getElementById("content")
println content.asText()

}

2 commenti:

Ahmed Ashour ha detto...

"HttpUnit" è un progetto diverso rispetto "HtmlUnit"

Davide Rossi ha detto...

Assolutamente si, un piccolo lapsus nel titolo... ;-)