# Website Crawler programmieren



## croni (7. Jul 2010)

Hallo zusammen,

ich hab' da ein Problem, bei dem ich als Java-Neuling nicht weiterkomme...

Und zwar möchte ich einen Website Crawler programmieren. Webseiten laden und darin Links erkennen funktioniert auch schön, aber ich scheitere daran, alle Links zu verfolgen und eine Website auf diese Weise ganz zu erfassen.

Ich habe zwei Ansätze versucht:

1) Rekursion
Geht in etwa so: Erste Instanz der Klasse liest Startseite ein, erkennt Links und macht eine eigene neue Instanz von sich selbst pro erkannten Link.

Problem: wie wissen die einzelnen Instanzen dann voneinander, welche Links schon gecrawlt sind und welche nicht? Es gibt ja nicht sowas wie globale Variablen in Java, resp. die wären Bad Code Design.

2) Liste
Ich lese die Startseite ein, erkenne Links und füge diese Links in eine Liste ein, welche es abzuarbeiten gilt. Diese Liste wächst vorzu bei neu erkannten Links, was bei einem Iterator über die Liste eine 'Concurrent Modification Exception' auslöst. Geht also auch nicht...

Wer weiss hier was? Ich hoffe, ich konnte das Problem einigermassen verständlich darlegen...


----------



## ARadauer (7. Jul 2010)

liste und keinen iterator verwenden ;-)


```
import java.util.ArrayList;



public class Test  {

   public static void main(String[] args) throws InterruptedException {

      ArrayList<String> list = new ArrayList<String>();
      list.add("Link 1");
      list.add("Link 2");
      for(int i = 0; i < list.size(); i++){
         System.out.println(list.get(i));
         list.add("neuer Link "+i);
         Thread.sleep(1000);
      }
   }

}
```

benutzt du mehrere threads?


----------



## Generic1 (7. Jul 2010)

Eine ConcurrencyModification wird ausgelöst, wenn mehrere Threads auf eine List o.ä zugreifen,
Mein Vorschlag mal: 


```
public class CrawlerThread extends Thread {

public void run() {
  try {
    crawl(root);
    }
  catch(InterruptException e) {
    }
}
}
```


----------



## fastjack (7. Jul 2010)

Den Iterator kannst Du schon verwenden. Du mußt nur in der Schleife aufpassen, daß wenn Du die zugrundeliegende Datenstruktur änderst, das über die Iterator-Methoden machst.
Beim Speichern von Links und anschließendem Suchen, ob ein Link schon vorhanden ist, würde ich eine Map verwenden, darin kannst Du viel effizienter Suchen, als bei einer stetig wachsenden Liste, bei der Du im worst case alle Elemente auf Gleichheit prüfen mußt.


----------



## fastjack (7. Jul 2010)

@generic1 er meint die ConcurrentModificationException, die wird u.a. ausgelöst, wenn der Iterator mitbekommt, das seine zugrundeliegende Datenstruktur ohne sein Mitwirken geändert wurde.


----------



## slawaweis (7. Jul 2010)

croni hat gesagt.:


> 1) Rekursion
> Geht in etwa so: Erste Instanz der Klasse liest Startseite ein, erkennt Links und macht eine eigene neue Instanz von sich selbst pro erkannten Link.
> 
> Problem: wie wissen die einzelnen Instanzen dann voneinander, welche Links schon gecrawlt sind und welche nicht? Es gibt ja nicht sowas wie globale Variablen in Java, resp. die wären Bad Code Design.


sie brauchen eine gemeinsame Schaltzentrale, wie z.B. bei Flugzeugen am Flughafen, die alle vom Kontrollturm koordiniert werden. Der Kontrollturm muss nicht global sein, es muss nur jeweils eine Referenz jeder neuen Instanz des Crawlers übergeben werden.



croni hat gesagt.:


> 2) Liste
> Ich lese die Startseite ein, erkenne Links und füge diese Links in eine Liste ein, welche es abzuarbeiten gilt. Diese Liste wächst vorzu bei neu erkannten Links, was bei einem Iterator über die Liste eine 'Concurrent Modification Exception' auslöst. Geht also auch nicht...


was Du jetzt brauchst ist keine Liste, sondern eine Schlange. In diesem konkreten Fall die java.util.concurrent.LinkedBlockingQueue .

LinkedBlockingQueue (Java Platform SE 6)

Slawa


----------



## fastjack (7. Jul 2010)

Als Java-Neuling würde ich das jetzt erstmal so programmieren, das es sequentiell läuft. Also jeder Link nacheinander bearbeitet wird. Wenns dann läuft und Du dann verstanden wie es funktioniert, dann kannst Du es immer noch nebenläufig programmieren. Erst mal einfach, danach komplex.


----------

