Crawler selbst geschreiben: OutOfMemoryError

Hallo!

Für meine Masterarbeit bin ich dabei einen Crawler zu schreiben. Ich muss eine Strukturanalyse des E-Tourismus Marktes durchführen. Dazu muss ich einen Webgraphen erstellen und möchte z.B. die Anzahl der In-Links sowie der Out-Links einer Seite bestimmen.

Ich lade eine Seite mit folgendem Befehl runter:

Java:
referenz = new URL(url);
is  = new InputStreamReader(referenz.openStream());
in  = new BufferedReader(is);
            
while ((zeile=in.readLine())!=null) {
        while (zeile.indexOf("<a href=\"http://")!=-1) {
....

Durchsuche dann die Seite nach Links und trenne externe und interne Links, die ich dann in der Datenbank speichere. Wenn alle internen Links durchgearbeitet sind gehe ich zum ersten gefundenen externen Link und durchsuche diese Seite nach links usw.
Um die In- und Out-Links zu bestimmen speichere ich noch zusätzlich pro externen Link eine Tabelle (wenn Datenbank) oder ein File in welchem ich dann schreibe wohin der Link führt oder woher er kommt.

Leider komme ich immer zu einem java.lang.OutOfMemoryError.

Meine Frage an euch ist:

Ist es überhaupt möglich einen Crawler zu schreiben der nicht irgendwann auf dieses Problem stößt, vorausgesetzt man arbeitet mit einem einzigen "normalen" Rechner und wenn ja wie?

Bisher arbeite ich nicht mit Threads und soviel ich verstanden habe würde dies das Problem auch nicht lösen.
Ich setze immer alle Objekte auf null und starte dann manuell den Garbage Collector. Dies hilft zwar ein bisschen, aber nicht viel.
Es macht wenig Unterschied ob ich zur Speicherung der In- und Out-Links die Datenbank oder Files verwende.

Ich würd mich freuen wenn mir jemand weiterhelfen könnte.

Grüße,
Roland
 

madboy

Top Contributor
Wie sind deine Speichereinstellungen für die JVM? Der Parameter "-Xmx" ist hier die erste Anlaufstelle :)
Versuche mal, dein Programm mit
Code:
java -Xmx500m -jar deinProgramm.jar
zu starten (falls du ein .jar zum Ausführen hast).

Grundsätzlich kann es natürlich trotzdem zu OutOfMemoryExceptions kommen wenn ich dich richtig verstanden habe und du das komplette Internet speichern willst und du nicht alles wieder aufräumst ;-)

Um Speicherproblemen auf die Spur zu kommen ist ein Blick auf jvisualvm nicht verkehrt, einfach mal danach suchen (Netz und/oder Forum).
 

Empire Phoenix

Top Contributor
Linktiefe vonner startsetie angeben können. Das internet ist zu groß um es einfach mal so zu durchforsten.
Andere idee, Alles !!!!! inne sql packen und nur jeweils eine einzige seite geladen haben und deren links parsen, speichern ,nächste laden (und nicht per rekursion alle alten sites merken)
 
Bevor du dich unglücklich machst schau dir mal diesen Crawler an:

Java Concurrency in Practice

und da unter anderem
5.9 Starting the desktop search.
7.17 Shutdown with poison pill.

Soviel ich von dem verstanden habe muss ich eine Art Liste führen mit Threads die ich dann abarbeite bzw. hinzufüge...

Wieso spart das Speicher? Ist das nicht so dass damit nur mehrere Seiten "gleichzeitig" gecrawlt werden können?
 

MQue

Top Contributor
Speicher weiß ich jetzt nicht ob es spart aber schneller ist es auf jeden Fall, Speicher sollte bei sowas eher keine Rolle spielen, Konzept geht meiner Meinung nach vor Speicher sparen.
Bei größeren Projekten ist das wieder was anderes, da würd ich dann auch auf den Speicher schaun, die JVM kann bis zu 1GB allokieren, das dürfte genug sein für dein Problem.
 
M

maki

Gast
^ Er hat doch ein Speicherproblem ;)

Nebenbei, die JVM kann mehr als 1GiB Speicher allokieren.
 
Vielen Dank nochmal für die Antworten.

Ich hab jetzt mal 1024 MB Speicher für die VM reserviert und das Programm läuft schon ziemlich lange. Hänge leider jetzt an einem anderen kleinen Problem und meld mich dann wieder wenn ich weiter bin...
 
Also jetzt funktioniert wieder alles. Ich habe jetzt auch die Anzahl der Links pro Seite beschränkt.

Zusammenfassend muss man also folgendes beachten wenn man einen großen Teil des Netzes crawlen will:
  • JVM soviel wie möglich Speicher geben
  • Anzahl der Links pro Seite begrenzen
  • Objekte immer null setzen und GarbageCollector manuell starten

Intern habe ich folgende Dinge implementiert um die Anzahl der Seiten zu reduzieren:
  • Dynamische Links weglassen
  • Einen Algorithmus der checkt wie lange kein externer Link mehr gefunden wurde und wenn eine bestimmte Größe erreicht wurde crawlen der Seite abbrechen und mit neuer Seite beginnen
  • Links die auf ein paar Zeichen begrenzt ähnlich sind nicht nochmal durchsuchen
  • Noch nicht implementiert aber möglich: Wenn man nur Seiten zu einem bestimmten Thema sucht die Seite nach bestimmten Wörtern abchecken

Freu mich über weitere Ideen.

Grüße,
Roland
 
Jetzt hab ich für mich eine adäquate Lösung wie ich auch das ganze Netz durchsuchen kann :):

Einfach wenn der OutOfMemoryError kommt die Domain merken die man zuletzt gecrawlt hat und beim Neustart mit dieser Domain fortfahren. Nachdem das Programm eh fast einen Tag läuft bis der OutOfMemoryError kommt ist das kein großer Aufwand.
 

FArt

Top Contributor
JVM soviel wie möglich Speicher geben
Kann bei speicheraufwendigen Applikationen von Vorteil sein.
Anzahl der Links pro Seite begrenzen
Ist eine Optimierungsmöglichkeit, was aber dem gewünschten Ergebnis entsprechen muss.
GarbageCollector manuell starten
Das ist definitiv unnötig und kann u.U. mehr Performance kosten als es bringt. Die VM weiß schon, wann der GC laufen sollte. Konfiguriere lieber den GC, damit z.B. ein anderer Algorithmus verwendet wird, wenn dir das Defaultverhalten nicht taugt.
Einfach wenn der OutOfMemoryError kommt die Domain merken die man zuletzt gecrawlt hat und beim Neustart mit dieser Domain fortfahren. Nachdem das Programm eh fast einen Tag läuft bis der OutOfMemoryError kommt ist das kein großer Aufwand.
Also wenn ich mit dem Auto gegen die Wand gefahren bin, schiebe ich es zurück, repariere es vor Ort und fahre einfach weiter als wäre nichts geschehen... interessante "Lösung".

Meine Lösung wäre glaube ich besser:
Ich würde mich fragen: was benötigt denn so viel Speicher? Kann ich denn nicht die meisten Daten schon längst Langzeit- oder zumindest Kurzzeitpersistieren und somit Hauptspeicher einsparen? Gibt es u.U. bessere (besser, weil sparsamer im Hauptspeicherverbrauch) Algorithmen um den Links zu folgen als der, den ich derzeit benutze? Ist Clustering eine (Teil-)Lösung?

Ich behaupte: es geht mit weniger Speicherverbrauch und ohne OutOfMemory. Das "Problem" ist ein grundlegender Designfehler und nicht im Code (oder der VM Konfiguration) zu suchen.
 
Zuletzt bearbeitet:
Gibt es u.U. bessere (besser, weil sparsamer im Hauptspeicherverbrauch) Algorithmen um den Links zu folgen als der, den ich derzeit benutze?

Ja am Algorithmus könnte ich noch basteln

Kann ich denn nicht die meisten Daten schon längst Langzeit- oder zumindest Kurzzeitpersistieren und somit Hauptspeicher einsparen?

Mache ich bereits. Mit Kurzzeitpersistieren habe ich mich allerdings noch nicht außeinandergesetzt.

Ist Clustering eine (Teil-)Lösung?

Was verstehst du unter Clustering, könntest du das genauer beschreiben?

Vielen Dank!
 
T

tuxedo

Gast
Also wenn ich mit dem Auto gegen die Wand gefahren bin, schiebe ich es zurück, repariere es vor Ort und fahre einfach weiter als wäre nichts geschehen... interessante "Lösung".

Das hab ich mir auch eben gedacht. Viel erschreckender finde ich allerdings dass das ne "Masterarbeit" wird.

Mit einem Profilder (der von Eclipse, der von Netbeans, JVisualVM (in jedem aktuellen JDK enthalten) oder Yourkit Java Profiler (Java Profiler - .NET Profiler - The profilers for Java and .NET professionals), oder oder oder) kommt man der Sache ganz schnell auf den Grund. Da lassen sich sogar automatisch Heap-Snapshots erstellen wenn der Heap zu XX% vollgelaufen ist. Einfach starten, warten bis es kracht und dann den Snapshot durchschauen wo zuviele Daten rumliegen die da nicht rumliegen müssten.

Die vorgehensweise hier erinnert mich an meine indischen Kollegen: "Wie? Problem? Ursache? Ach was, wieso? Wir bauen ein neues Stück Code das mit dem Symptomen umgehen kann. Dann sparen wir uns die Ursachenforschung."

- Alex
 
Viel erschreckender finde ich allerdings dass das ne "Masterarbeit" wird.

Das Thema der Masterarbeit ist es, nicht einen Crawler zu schreiben, sondern eine Strukturanalyse des E-Tourismusmarktes in Österreich durchzuführen. Wie der Crawler funktioniert ist nebensächlich, Hauptsache er liefert die Daten.
Wäre das Thema einen Crawler zu schreiben würde ich dir wohl recht geben.

Danke für deinen weiteren Tipp

Grüße,
Roland
 

FArt

Top Contributor
Was verstehst du unter Clustering, könntest du das genauer beschreiben?
Dein Problem ist eines, das sich sehr gut skalieren ließe, d.h. mehrere Prozesse übernehmen die Arbeit. Das könnte auch Geschwindigkeitsvorteile bieten.

Wenn ich mir aber die Beschreibung ansehe, was dein Crawler so alles machen soll, dann behaupte ich, ist dafür nicht viel Hauptspeicher notwendig. Die gesamte Datenhaltung kann in der Datenbank passieren, wozu geht denn der Hauptspeicher flöten?

Beides erwähne ich hier nur, weil dies eine Community ist und vielleicht jemand mal tatsächlich als Programmierer über diesen Thread stolpert. Für dich ist vermutlich das Aufhören und weitermachen die einfachste, pragmatische Lösung. Das könntest du sogar automatisieren (java command line option: -XX:OnError startet ein Skript mit der Applikation) ;-)
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
B Web Crawler Algorithmen mit Jsoup Allgemeine Java-Themen 3
P Crawler Allgemeine Java-Themen 6
M Queue für spider/crawler? Allgemeine Java-Themen 2
Q Suche Crawler Allgemeine Java-Themen 2
R Crawler mit Java schreiben Allgemeine Java-Themen 5
I Hibernate Envers - Aufruf der Methode zum Speichern selbst ausführen oder managen? Allgemeine Java-Themen 0
P JavaFX Anwendung beendet sich selbst nur als Jar Allgemeine Java-Themen 40
L Excel Datei löscht sich selbst im Programm - Java Allgemeine Java-Themen 3
G Beendet sich der Thread selbst?! Allgemeine Java-Themen 3
W IDEA IntelliJ Build-Management-Tool selbst programmieren Allgemeine Java-Themen 2
Tausendsassa Threads Einen Thread sich selbst schließen lassen Allgemeine Java-Themen 17
S Mit Generics Klasse erstellen die selbst T erweitert..? Allgemeine Java-Themen 4
S Shape selbst rendern..? Allgemeine Java-Themen 5
N Automatisches einfügen einer selbst generierten ID in Klasse mit Annotation Allgemeine Java-Themen 8
M Programm startet sich selbst neu, alte Logfiles bleiben gesperrt Allgemeine Java-Themen 2
Z Klassen ArrayList selbst machen Allgemeine Java-Themen 5
R JRE Ablaufdatum seit 7u10 - Probleme bei selbst ausgelieferter JRE bekannt? Allgemeine Java-Themen 3
J kann eine .jar sich selbst verschieben? Allgemeine Java-Themen 6
C Eclipse Probleme bei selbst erstelltem Algorithmus Allgemeine Java-Themen 2
Q Zeit in GUI selbst aktualisieren Allgemeine Java-Themen 5
D PriorityQueue selbst implementieren Allgemeine Java-Themen 15
K Serialisierung komplett selbst machen Allgemeine Java-Themen 13
W Annotations selbst erstellen und auswerten Allgemeine Java-Themen 4
M Selbst geschriebener InputStreamReader über einen beliebigen InputStream Allgemeine Java-Themen 4
J Können Programme sich selbst erweitern? Allgemeine Java-Themen 6
J Objekt selbst ertellen möglich? Allgemeine Java-Themen 6
N JFrame Icon selbst erzeugen Allgemeine Java-Themen 2
PAX Applikation sich selbst neu starten lassen Allgemeine Java-Themen 27
P Eigene Klasse kopieren die auf sich selbst refferenziert Allgemeine Java-Themen 8
R synchronized "gegen sich selbst" Allgemeine Java-Themen 5
J BufferedWriter schreibt von selbst ein "" Allgemeine Java-Themen 12
H JButtons selbst gestallten Allgemeine Java-Themen 6
V Sich selbst kopieren (Jar- Datei) Allgemeine Java-Themen 3
ARadauer programm soll sich selbst ändern können Allgemeine Java-Themen 20
F Klasse soll sich selbst returnieren mit entsprechendem Typ. Allgemeine Java-Themen 15
V Avatar selbst programmieren Allgemeine Java-Themen 4
E externe Anwendung aufrufen und sich selbst beenden Allgemeine Java-Themen 8
F Kann Applet installierte JVM selbst auswählen? Allgemeine Java-Themen 4
R DropTarget auch für Applet selbst Allgemeine Java-Themen 2
M vererbung einer "selbst-instanzierungs-klasse" Allgemeine Java-Themen 16
J ID selbst vergeben Allgemeine Java-Themen 2
E Einer Methode sich selbst übergeben . ? Allgemeine Java-Themen 5
J Fenster mit paint Methode selbst zeichnen Allgemeine Java-Themen 3
C Vectoren befuellen sich von selbst Allgemeine Java-Themen 2
P Programm selbst starten lassen Allgemeine Java-Themen 2
B Installshield selbst gemacht Allgemeine Java-Themen 3
E Objekt serialisiert sich selbst Allgemeine Java-Themen 2
ARadauer Schon mal jemand für Ungarn CSV Datein geschreiben? Allgemeine Java-Themen 2

Ähnliche Java Themen

Neue Themen


Oben