# WebCrawler in Java



## Gelöschtes Mitglied 35125 (5. Sep 2012)

hallo leute,

vor kurzem habe ich mich für ein praktikum beworben und habe auch schon eine antwort wo ich aufgefordert werde ein web crawler in java zu schreiben.

der web crawler soll folgendes können:

-den inhalt einer webseite holen
-aus dem inhalt die links extrahieren
-die extrahierten links crawlen(zurück zu step 1)
-bei 1000 links schluss machen

da ich noch keinen plan von webcrawlern hatte war ich erstmal ein wenig baff, habe mich nu erstmal schlau gemacht und ein flussdiagramm erstellt um zu gucken ob ich die sache kapiert habe. ich will nichts großes programmieren, halt nur ein crawler der den o.g. anforderungen entspricht. 

ich habe also vor diesen thread als eine art mindmap zu nutzen wo ihr mir hoffentlich auch ein paar kommentare/kritik/tipps geben könntet

gibt für crawler schon klassen? also womit man aus html-dokumenten die url & links rausfiltern kann?

hab das flussdiagramm als anhang beigefügt, hoffe dass ich da keine fehler gemacht habe...

greetz


----------



## Gast2 (5. Sep 2012)

Hm, bin mir nicht ganz sicher ob du das mit dem crawler richtig verstanden hast, zumindest wär das Kontrollflussdiagramm dann falsch.
Du musst jede Seite die du durch neue Links erreichst wieder nach Links durchsuchen und damit deine Queue füllen. Wenn du dann bei insgesamt 1000 durchsuchten Links bist brichst du ab.

Was dir helfen wird sind folgende Klassen:
- URL, zum auslesen einer Seite
- Pattern und Matcher, zum rausfiltern der Links


----------



## Gelöschtes Mitglied 35125 (5. Sep 2012)

hi elke, danke erstmal für deine rasche antwort!

meinst du dass der queue-counter bei jeder seite neu anfängt? weil ich habe mir das so vorgestellt:

rootSeite eingeben, counter von queue auf 0 setzen
rootSeite nach Links (=weiteren Seiten) durchsuchen 
gefundene links in queue packen, für jede seite counter + 1
solange schritt 2 wiederholen bis counter = 1000

habe das flüssdiagramm nochmal ein wenig überarbeitet da mir selber ein fehler aufgefallen ist


----------



## Gast2 (5. Sep 2012)

Nein, der Counter fängt nicht bei jeder Seite wieder bei 0 an. Du würdest sonst sehr lange suchen müssen  Den Counter erhöhst du immer wenn du eine Seite ausließt.


----------



## Ark (5. Sep 2012)

EikeB hat gesagt.:


> - Pattern und Matcher, zum rausfiltern der Links


Na ja, na, ja … sicherer/besser/komfortabler geht das mit einem HTML-Parser. Interessanterweise wurde erst neulich nach so was gefragt.

@dsordrlyPrgrmng: Für einfache Fälle könnte man auch zu wget greifen. Eventuell kannst du dir da auch das eine oder andere abschauen. 

Ark


----------



## Gelöschtes Mitglied 35125 (5. Sep 2012)

@ elke, dann verstehe ich nicht ganz was an dem flussdiagramm net stimmt, könntest du mir das ein wenig genauer erklären?

@ark, danke ich werde mir erstmal die genannten libs angucken, ich muss ja dann noch alles erklären können wenns dazu kommt, also wäre das schon schön wenns ne etwas einfachere methode ist


----------



## z-mon (5. Sep 2012)

Hallo dsordrlyPrgrmng,

mit HTMLUnit wird das ein Dreizeiler ... fast 

Viel Erfolg


----------



## Kjubert (5. Sep 2012)

z-mon hat gesagt.:


> Hallo dsordrlyPrgrmng,
> 
> mit HTMLUnit wird das ein Dreizeiler ... fast
> 
> Viel Erfolg



Naja aber wär doch irgendwie cooler das selber zu machen, oder? Die Aufgabe ist ja nun wirklich nicht allzu schwer.

Der Ablauf sollte "ganz einfach" dieser sein, wenn ich das richtig verstanden habe:


URL zum Auslesen setzen
Seitenquelltext auslesen
Quelltext nach Links durchsuchen und Links is Liste o.ä. speichern
Counter (oder was auch immer) um 1 erhöhen
Prüfen, ob Counter == 1000 (wenn ja -> ENDE, wenn nein -> nächster Schritt)
Erste URL in der Liste als URL zum Auslesen setzen (also ab Schritt 1 wiederholen)

Das schaffst du schon


----------



## z-mon (6. Sep 2012)

Zu klären ist noch ob es 1000 verschiedene Domains sein sollen. Wenn dem so ist, musst du die gescannten Domains mitschneiden (ggf. die Basis URL aus der vollständigen URL extrahieren) und auf bereits gescannd prüfen.


----------



## hüteüberhüte (6. Sep 2012)

dsordrlyPrgrmng hat gesagt.:


> @ elke,



Doch nicht elke  , EikeB

Also ich würde solche Aufgaben einfach runterprogrammieren und nicht erst noch mit UML etc. beginnen. Aber als Ergebnispräsentation wäre das natürlich schöner.

Anregungen:
- Mehrere Threads, die eine Page laden,
- threadsichere Queue (o.ä. Datenstruktur),
- eine Domain nur einmal (oder max. x-mal) laden,
- XML-/HTML-Parser vs. Regex
- usw.

Zum Flussdiagramm:

```
que.add(ersteUrl)
c = 0
while (c < 1000 && !que.isEmpty()) {
  que.add(read(que.get()))
  c++
}
```


----------



## Templarthelast (6. Sep 2012)

hüteüberhüte hat gesagt.:


> ```
> que.add(ersteUrl)
> c = 0
> while (c < 1000 && !que.isEmpty()) {
> ...




Das wäre natürlich eine schöne Lösung, wenn man einen Thread hätte, welcher die Inhaltsangaben der Seiten durchsucht und die richtigen Links zu einer quue hinzufügt. Diese Que würde dann von einem oder meheren anderen Threads durchlaufen wird.  
Allerdings finde finde ich soetwas für jemanden, der einen crawler nur für ein Praktikum entwickeln soll, etwas überdimensioniert. 

@TO
Falls du eine einfache und schnelle Lösung suchst würde ich, wie schon einmal angesprochen über das HTMLUnit-framework gehen. Die andere Möglichkeit, welche wahrscheinlich auch besser bei deinem Arbeitgeber ankommen würde, wäre ein eigener htmlParser, welcher die Seite per HTTPStream ließt und dann auswertet.


----------



## Kjubert (6. Sep 2012)

Aber ist das denn alles nötig? Gestern Abend konnt ich schlecht schlafen, da hab ich das mal ausprobiert und so gehts eigentlich fix:
Erstmal den Quelltext auslesen (kann man ja machen, wie man will), und dann so in etwa die Links rausfiltern:


```
private Set<URL> getLinksFromHTMLSource(String htmlSource, URL from){
	Set<URL> linkSet = new HashSet<URL>();
	int currentIndex = 0;
	int endIndex = 0;
	String currentLink;
	
	while((currentIndex = htmlSource.indexOf("href=\"", currentIndex + 1)) >= 0){
		endIndex = htmlSource.indexOf("\"", currentIndex + 8);
		currentLink = htmlSource.substring(currentIndex + 6, endIndex);
		
		if (currentLink.indexOf("http") < 0) currentLink = from.getProtocol()
														 + "://"
														 + from.getHost()
														 + from.getPath();
		
		try {
			if (currentLink.length() > 1) linkSet.add(new URL(currentLink));
		} catch (MalformedURLException e) {}
	}
	return linkSet;
}
```

Also der funktionierte auf Anhieb - vielleicht kann mir da ja irgendwer von den erfahreneren hier mal auf die Finger hauen, wenn ich irgendwo grobe Verbrechen begangen hab


----------



## Empire Phoenix (6. Sep 2012)

Kleinigkeiten sind auf jedenfall noch, was wenn ich im html 'href ="' statt 'href="' habe?
Also kurz leerzeichen behandlung beim href evt noch benötigt. 

Zudem, was wenn sonderzeichen inner url drinnen sind? Browser wnadeln die automatisch um die url klasse nciht soweit ich we iß, würde ich mal testen.


----------

