bloggers bloggers

Marco Napolitano
Messaggi: 79
Stelle: 0
Data: 17/02/22
Jader Jed Francia
Messaggi: 63
Stelle: 0
Data: 18/02/21
Paolo Gambetti
Messaggi: 2
Stelle: 0
Data: 11/11/19
Katia Pazzi
Messaggi: 1
Stelle: 0
Data: 27/06/19
Ezio Lombardi
Messaggi: 11
Stelle: 0
Data: 10/04/18
Chiara Mambretti
Messaggi: 25
Stelle: 0
Data: 27/02/17
Serena Traversi
Messaggi: 3
Stelle: 0
Data: 21/07/16
Francesco Falanga
Messaggi: 8
Stelle: 0
Data: 14/06/16
Antonio Musarra
Messaggi: 2
Stelle: 0
Data: 18/11/13
Simone Celli Marchi
Messaggi: 6
Stelle: 0
Data: 09/07/13
Indietro

Screen Scraping: come "raschiare" il testo da una pagina web

Parecchi anni fa un nostro cliente ci commissionò la realizzazione di una piattaforma di screen scraping distribuita che costituiva un modulo del suo sistema di acquisti online.

Il progetto fù un bagno di sangue perchè, tra le mille cose, non finivamo di scrivere un agente che "parsava" il codice della pagina che il sito di riferimento ce la cambiava e tutto il lavoro andava rifatto o quanto meno sistemato!

Ma provate voi a manutenere un parser di html che assume degli indexOf su delle stringhe e cerca di tirarci fuori del testo"ripulito"!:)

L'altro giorno, mi sono trovato a dover "raschiare" dal sito di pagine gialle un po' di numeri di telefono, per fare del telemarketing.

Ripensai al lavoro che facemmo per il cliente e mi scoraggiai non poco.

Poi mi misi a cercare su web se nel frattempo le tecnologie per fare screen scraping si erano evolute: come spesso accade, non si è mai gli unici ad affrontare un problema, per fortuna!:)

Facendo un po' di ricerca sul web, mi sono imbattuto in TagSoup, una libreria java SAX-Compliant che anzichè parsare XML well-formed parsa HTML scritto male.

E mi sono trovato a scrivere un agente che, a logica era lo stesso di anni prima, ma in quanto a leggibilità del codice era tutta un'altra storia!

Anche perchè avere un sax parser significa poi avere dei documenti sui quali fare query xpath.. Molto più pratico che fare indexOf su stringhe.. :D

Di seguito lo snippet che ho usato per fare screen scraping su pagine gialle!

// Creo un'istanza del parser

SAXBuilder builder = new SAXBuilder("org.ccil.cowan.tagsoup.Parser");

// recupero il dom della pagina ripulito
Document doc = builder.build(url);

// recupero tutti i blocchetti di testo della pagina:

// xpath e non indexOf!:)
List<Element> list = getListElement(doc.getRootElement(),

"//h:div[@class = 'listing-client-line-pg clearfix']");
Iterator<Element> i = list.iterator();
while (i.hasNext()) {
Element currentElement = i.next();
String nomeAzienda = getText(currentElement, "./h:div/h:h3/h:a");
if (nomeAzienda == null || "".equals(nomeAzienda))
nomeAzienda = getText(currentElement, "./h:div/h:h3");
Element addressElement = getSingleElement(currentElement,

"./h:div/h:div/h:div/h:address");
String cap = getText(addressElement,

".//h:span[@class = 'postal-code']");
String locality = getText(addressElement,

".//h:span[@class = 'locality']");
String region = getText(addressElement,

".//h:span[@class = 'region']");
String streetAddress = getText(addressElement,

".//h:p[@class = 'street-address']");
List<String> telefoni = new ArrayList<String>();
List<Element> tel = getListElement(addressElement,

".//h:p[@class = 'tel']");
Iterator<Element> telIterator = tel.iterator();
while (telIterator.hasNext()) {
telefoni.add(getText(telIterator.next(), "."));
}
// Stampo il risultato in csv style, piu' comodo da importare

// nel nostro CRM!
printRecord(nomeAzienda, cap, locality, region, streetAddress,

(String[]) telefoni.toArray(new String[telefoni.size()]));

}

// Utility methods utilizzati nello snippet

private JDOMXPath getXPath(String xPathQuery) throws Exception {
JDOMXPath path = new JDOMXPath(xPathQuery);
path.addNamespace("h","http://www.w3.org/1999/xhtml");
return path;
}

public Element getSingleElement(Element currentElement,

String xPathQuery) throws Exception {
JDOMXPath path = getXPath(xPathQuery);
return (Element) path.selectSingleNode(currentElement);
}

public List<Element> getListElement(Element currentElement,

String xPathQuery) throws Exception {
JDOMXPath path = getXPath(xPathQuery);
return (List<Element>) path.selectNodes(currentElement);
}

public String getText(Element currentElement, String xPathQuery)

throws Exception {
Element element = getSingleElement(currentElement, xPathQuery);
if (element != null)
return element.getText();
else
return "";
}

Bhe, che dire:il problema di dover rimettere mano a tutto se qualche cosa cambia nel sito target è rimasto, ma almeno il codice ora è sicuramente molto più manutenibile!:)

Precedente
Commenti
Nessun commento. Vuoi essere il primo.