# Alle Links eines HTML Dokuments extrahieren



## Thomas Darimont (29. April 2005)

Hallo!


```
/*
 * Created on 29.04.2005@11:54:21 by Darimont
 *
 * TODO Licence info
 */
package de.tutorials;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;

import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;

/**
 * @author Darimont
 * 
 * TODO Explain me
 */
public class LinkExtractor {

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

		URL url = new URL("file:/c:/tutorials.htm");
		URLConnection con = url.openConnection();

		BufferedReader br = new BufferedReader(new InputStreamReader(con
				.getInputStream()));

		HTMLEditorKit editorKit = new HTMLEditorKit();
		HTMLDocument htmlDoc = new HTMLDocument();
		htmlDoc.putProperty("IgnoreCharsetDirective", Boolean.TRUE);
		editorKit.read(br, htmlDoc, 0);

		HTMLDocument.Iterator iter = htmlDoc.getIterator(HTML.Tag.A);
		while (iter.isValid()) {
			System.out.println(iter.getAttributes().getAttribute(
					HTML.Attribute.HREF));
			iter.next();
		}

	}
}
```

Gruß Tom


----------



## Folliot (3. Juli 2005)

Hallo Tom,
ein schönes Programmfragment, könntest Du es allerdings um ein paar Erläuterungen für Java Neulinge erweitern? ;-) 

Zunächst einmal verstehe ich nicht, warum das Programm bei mir zwar kompiliert aber dann nur eine execption in der Klasse main ausgibt: "Exception in thread "main" java.lang.NoClassDefFoundError: LinkExtractor...

Ich meine es wird gar keine Datei Klassendatei namens LinkExtractor.class angelegt...

Wo liegt mein Fehler?

Vielen Dank für Deine Hilfe, Grüsse Folliot


----------



## Flokati (20. April 2007)

Wenn ich den Tag von "A" auf etwas anderes zB "P" ändere:

```
HTMLDocument.Iterator iter = htmlDoc.getIterator(HTML.Tag.P);
```
erhalte ich nur noch eine "NullPointerException"!


----------



## thomas_groetzner (15. Januar 2008)

Hallo,

das Beispiel funktioniert bei mir für "a href" wunderbar. Wenn ich es aber umstelle auf bspw. "img src" dann wird nichts mehr gefunden.

Hier mein der minimal modifizierte Code, das Eingabedokument und die Ausgabe:

Code:

```
public static void main( String[] args ) throws Exception
    {
        
        URL url = new URL( "file:/c:/tutorials.htm" );
        URLConnection con = url.openConnection();
        
        BufferedReader br = new BufferedReader( new InputStreamReader( con.getInputStream() ) );
        
        HTMLEditorKit editorKit = new HTMLEditorKit();
        HTMLDocument htmlDoc = new HTMLDocument();
        htmlDoc.putProperty( "IgnoreCharsetDirective", Boolean.TRUE );
        editorKit.read( br, htmlDoc, 0 );
        
        {// IMAGES
            HTMLDocument.Iterator iter = htmlDoc.getIterator( HTML.Tag.IMG );
            while( iter.isValid() )
            {
                System.out.println( "img: " + iter.getAttributes().getAttribute( HTML.Attribute.SRC ) );
                iter.next();
            }
        }
        
        {// LINKS
            HTMLDocument.Iterator iter = htmlDoc.getIterator( HTML.Tag.A );
            while( iter.isValid() )
            {
                System.out.println( "a: " + iter.getAttributes().getAttribute( HTML.Attribute.HREF ) );
                iter.next();
            }
        }
    }
```

Eingabedokument (mit 6x a href und 1 x img src):

```
<html>
	<head>
	</head>
	<body>
		<img src="hugo.gif">x</img>
<a href="bla1"/>
		<a


		href

		=


		"bla2"


		>XXX</a>
		<a href="bla3"><p>sdfsdfsdf</p>XX1</a>
		<p>fhdsfksdhka<b>fdfdfdf</p>
		<a href="bla4">XXX2</a>
		<a href="bla5">XXX3</a>
		<img src="hugo.gif">x</img>
		dfdsfdfs
		dfsdf
		s<a href="bla6">XXX4</a>
		df
</body
</html>
```

und hier die Ausgabe ohne IMG:

```
a: bla1
a: bla2
a: bla3
a: bla4
a: bla5
a: bla6
```

Kann da jemand aufklären warum das für a-Tags geht und für p (wie beim Vorposter) und img dann nicht? Ist doch eigentlich kein Unterschied?

Ciao
Thomas Groetzner


----------



## Thomas Darimont (15. Januar 2008)

Hallo,


```
/*
 * Created on 29.04.2005@11:54:21 by Darimont
 *
 * TODO Licence info
 */
package de.tutorials;

import java.io.FileInputStream;

import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.HTML.Tag;

/**
 * @author Darimont
 * 
 * TODO Explain me
 */
public class LinkExtractor {

    public static void main(String[] args) throws Exception {
        HTMLEditorKit editorKit = new HTMLEditorKit();
        HTMLDocument htmlDoc = new HTMLDocument();
        htmlDoc.putProperty("IgnoreCharsetDirective", Boolean.TRUE);
        editorKit.read(new FileInputStream("c:/tutorials.html"), htmlDoc, 0);
        

        
        HTMLDocument.Iterator aTagIterator = htmlDoc.getIterator(HTML.Tag.A);
        while (aTagIterator.isValid()) {
            System.out.println(aTagIterator.getAttributes().getAttribute(
                    HTML.Attribute.HREF));
            aTagIterator.next();
        }
        
        HTMLDocument.Iterator imgTagIterator = htmlDoc.getIterator(HTML.Tag.IMG);
        while (imgTagIterator.isValid()) {
            System.out.println(imgTagIterator.getAttributes().getAttribute(
                    HTML.Attribute.SRC));
            imgTagIterator.next();
        }
    }
}
```

Ausgabe:

```
bla1
bla2
bla3
bla4
bla5
bla6
hugo.gif
hugo.gif
```

Gruß Tom


----------



## thomas_groetzner (15. Januar 2008)

Hallo Tom,

an dem Code von Dir sind ja nur die ersten Paar Zeilen (Lesen file/Lesen Stream) anders. Übersetzte ich das bei mir kommt auch der Output ohne die img-Tags raus.


Ich hab aber rausgefunden woran es liegt: das Problem steht und fällt mit der verwendeten JDK-Version. Der von mir gepostete Quellcode (und der von Dir auch) liefert:

mit j2sdk1.4.2_06 den fehlerhaften Output ohne die img-Tags
mit j2sdk1.6.0_01 neu übersetzt den korrekten Output incl. der img-Tags!

Ich hatte mit 1.4.2 nämlich auch keine

- table
- div
- ...

Tags bekommen (in den Fällen sogar null pointer exception, bei img einen leeren Iterator). Nur die a-Tags gingen komischerweise problemlos. Dann habe ich Eclipse auf 1.6 umgestellt und schon ging es. Schade nur dass ich in meiner Umgebung kein 1.6 verwenden darf. Dann parse ich eben doch selbst mit Regular Expressions.

Ciao und danke
Thomas Groetzner


----------



## Fulk (2. Juni 2008)

Ich hätte eine Frage zum HTMLEditorKit bzw. den Quelltexten.

Ist es auch möglich, sich nicht nur die Attribute (name=..., value=... usw.) von HTML-Tags ausgeben zu lassen, sondern auch das, was dahinter/zwischendrin steht?

Also aus 

```
<div>Hallo Welt!</div>
```
würde ich gerne "Hallo Welt!" extrahieren.

Vielen Dank!


----------



## criss (5. November 2008)

Fulk hat gesagt.:


> Ich hätte eine Frage zum HTMLEditorKit bzw. den Quelltexten.
> 
> Ist es auch möglich, sich nicht nur die Attribute (name=..., value=... usw.) von HTML-Tags ausgeben zu lassen, sondern auch das, was dahinter/zwischendrin steht?
> 
> ...


Hi,
ich habe die gleiche Frage wie Du. Hast Du schon eine Lösung für dein Problem?
Danke. Criss.


----------



## pelewee (23. Dezember 2008)

> Zitat:
> Zitat von *Fulk*
> 
> 
> ...


Hi. Dazu hätte ich evtl. eine Lösung für euch.


```
int length;
String text;
HTMLEditorKit editorKit = new HTMLEditorKit(); 
HTMLDocument htmlDoc = new HTMLDocument();

htmlDoc.putProperty("IgnoreCharsetDirective",Boolean.TRUE);
editorKit.read(new FileInputStream("c:/tutorials.html"), htmlDoc, 0);
HTMLDocument.Iterator iter = htmlDoc.getIterator(HTML.Tag.B);

        while (iter.isValid()) {
            length = iter.getEndOffset()-iter.getStartOffset();
            text = htmlDoc.getText(iter.getStartOffset(), length);
            System.out.println(text);
            iter.next();
        }
```
Hier wollte ich den Text ausgeben der "Fett" geschrieben wurde.
Mit dem "*length = iter.getEndOffset()-iter.getStartOffset()*;" bekommt ihr eure Satzlänge, die zwischen den Tags <b></b>steht, heraus.
Nun müsst ihr nur noch "*htmlDoc.getText(iter.getStartOffset(), length);*" aufrufen.

Hoffe ich konnte euch weiterhelfen 
Alternativ Lösungen gern gesehen.

Gruß Mike


----------



## herzeleid (11. August 2009)

Das ganze Funktioniert bei mir leider nur in einer IDE (netBeans / Eclipse), wenn ich das aber in einer Konsole (Linux) starte, bekomme ich irgendwann immer eine EOFException...

Die ganze Fehlermeldung:

```
Implement parseAny for FUNCTION
Implement parseAny for FUNCTION
Implement parseAny for FUNCTION
Implement parseAny for FUNCTION
couldn't parse: 0 6px
couldn't parse: 0 24px 0 6px
couldn't parse: 0 6px 0 24px
Implement parseAny for FUNCTION
Implement parseAny for FUNCTION
Implement parseAny for FUNCTION
Implement parseAny for FUNCTION
Implement parseAny for FUNCTION
Implement parseAny for FUNCTION
Implement parseAny for FUNCTION
Implement parseAny for FUNCTION
Implement parseAny for FUNCTION
Implement parseAny for FUNCTION
Implement parseAny for FUNCTION
Implement parseAny for FUNCTION
Exception in thread "main" java.lang.reflect.InvocationTargetException
   at java.lang.reflect.Method.invoke(libgcj.so.90)
   at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:56)
Caused by: gnu.javax.swing.text.html.parser.support.low.ParseException: IO Exception
   at gnu.javax.swing.text.html.parser.support.low.ReaderTokenizer.getTokenAhead(libgcj.so.90)
   at gnu.javax.swing.text.html.parser.support.Parser.error(libgcj.so.90)
   at gnu.javax.swing.text.html.parser.support.Parser.error(libgcj.so.90)
   at gnu.javax.swing.text.html.parser.support.Parser.parse(libgcj.so.90)
   at gnu.javax.swing.text.html.parser.GnuParserDelegator.parse(libgcj.so.90)
   at javax.swing.text.html.HTMLEditorKit.read(libgcj.so.90)
   at SEOSearch.getBacklinkSites(SEOSearch.java:85)
   at SEOSearch.main(SEOSearch.java:132)
   at java.lang.reflect.Method.invoke(libgcj.so.90)
   ...1 more
Caused by: java.io.EOFException: Early EOF in GZIP footer
   at java.util.zip.GZIPInputStream.readFooter(libgcj.so.90)
   at java.util.zip.GZIPInputStream.read(libgcj.so.90)
   at java.io.BufferedInputStream.refill(libgcj.so.90)
   at java.io.InputStreamReader.refill(libgcj.so.90)
   at java.io.InputStreamReader.read(libgcj.so.90)
   at java.io.BufferedReader.fill(libgcj.so.90)
   at java.io.BufferedReader.read(libgcj.so.90)
   at gnu.javax.swing.text.html.parser.support.low.ReaderTokenizer.readToken(libgcj.so.90)
   at gnu.javax.swing.text.html.parser.support.low.ReaderTokenizer.read(libgcj.so.90)
   at gnu.javax.swing.text.html.parser.support.low.ReaderTokenizer.getTokenAhead(libgcj.so.90)
```

Hintergrund warum ich sowas eigentlich brauche ist der, das ich für meinen Job ein Tool schreiben soll, mit dem man verschiedene Seiten nach einem definierten Link durchsucht.

Wenn jemand meint, die Idee das über den HTMLEditorKit ohne Swing zu machen sei suboptimal, wie könnte man das evtl. anders machen?
Seite zeilenweise streamen und dann innerhalb der Zeilen nach dem Link suchen?

Danke im Voraus für evtl. Antworten.


----------



## Thomas Darimont (11. August 2009)

Hallo,

lass die Anwendung mal mit einer normalen JVM laufen und nicht mit gcj...

Gruß Tom


----------



## herzeleid (11. August 2009)

hmpf...ok, ich gleb mir heute das Blind-Flag an die Stirn....

DANKE


----------



## Onkel Dirk (8. Februar 2010)

Hallo,

ich lese immer fleißig mit, habe aber auch noch eine Frage.

Wie kann ich den herausfinden ob der Link noch Attribute  rel="nofollow"  oder styles hat?

Und gibt es eine leicht verständliche Anleitung  vom HTMLEditorKit  für Anfänger wie mich?

Gruß 

Onkel Dirk


----------



## Wilson (4. August 2013)

Hallo Leute,

ich hätte da eine Frage, wäre froh für jede Hilfe.

ich habe hier gelesen das man dieses z.B. bla3 printen kann das klappt auch bei mir, nur möchte ich wissen ob man auch dieses XX1 ausgeben kann in der konsole.


```
<a href="bla3"><p>sdfsdfsdf</p>XX1</a>
```


bzw. an diesem beispiel das mein Problem auch betrift bekomme ich bla bla ausgespukt aber das "X" nicht. Wie bekomme ich das X in der Konsole ausgespukt?


```
<span class="quote"><span class="" title="bla bla">X</span> </span>
```

Vielen Dank im Voraus


----------

