2016-05-13 26 views
1

Ich bin ein Anfänger im Programmieren und versuche gerade, meinen ersten Web-Scraper mit JSoup zu erstellen. Bis jetzt bin ich in der Lage, die gewünschten Daten von einer einzelnen Seite meiner Zielseite zu bekommen, aber natürlich möchte ich irgendwie über die gesamte Seite iterieren.Wie erstelle ich einen NodeTraversor/NodeVisitor mit JSoup?

JSoup scheint eine Art Traversor/Besucher zu bieten (was ist der Unterschied?), Aber ich habe absolut keine Ahnung, wie ich das machen soll. Ich weiß, was Bäume und Knoten sind und kenne die Struktur meiner Zielseite, aber ich weiß nicht, wie ich ein Verleger-/Besucherobjekt (?) Erstellen und es über meine Site laufen lassen kann. Könnte es sein, dass es eine fortgeschrittene Java/oo-Magie bei der Arbeit gibt, von der ich nichts weiß?

Leider scheinen weder das Jsoup Kochbuch noch andere Threads die Details wirklich zu verdecken, also wenn mich jemand in die richtige Richtung schubsen könnte, wäre ich sehr dankbar.

Antwort

1

JSoup scheint eine Art von traverser/Besucher zu bieten (was ist der Unterschied?)

Die NodeTraversor wird durch alle Knoten unter und mit einem festgelegten Wurzelknoten effizient durchlaufen. Es wird keine Rekursion verwendet, sodass ein großes DOM keinen Stackoverflow erzeugt.

Die NodeVisitor (NV) ist der Begleiter von NodeTraversor (NT). Jedes Mal, wenn NT einen Knoten betritt ruft es die head Methode der NV auf. Jedes Mal, wenn NT einen Knoten verlässt, ruft er die tail-Methode der NV auf.

NT ist fertig und wird Ihnen von der Jsoup API zur Verfügung gestellt. Alles, was Sie tun müssen, ist NT eine NV-Implementierung zur Verfügung zu stellen.

Hier ist eine wirkliche Leben Umsetzung NodeVisitor von ElasticSearch source code genommen:

protected static String convertElementsToText(Elements elements) { 
    if (elements == null || elements.isEmpty()) 
     return ""; 
    StringBuilder buffer = new StringBuilder(); 
    NodeTraversor nt = new NodeTraversor(new ToTextNodeVisitor(buffer)); 
    for (Element element : elements) { 
     nt.traverse(element); 
    } 
    return buffer.toString().trim(); 
} 

private static final class ToTextNodeVisitor implements NodeVisitor { 
    final StringBuilder buffer; 

    ToTextNodeVisitor(StringBuilder buffer) { 
     this.buffer = buffer; 
    } 

    @Override 
    public void head(Node node, int depth) { 
     if (node instanceof TextNode) { 
     TextNode textNode = (TextNode) node; 
     String text = textNode.text().replace('\u00A0', ' ').trim(); // non breaking space 
     if (!text.isEmpty()) { 
      buffer.append(text); 
      if (!text.endsWith(" ")) { 
      buffer.append(" "); 
      } 
     } 
     } 
    } 

    @Override 
    public void tail(Node node, int depth) { 
    } 
}