Alle Links eines HTML Dokuments extrahieren

Thomas Darimont

Erfahrenes Mitglied
Hallo!

Code:
/*
 * 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
 
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
 
:confused:
Wenn ich den Tag von "A" auf etwas anderes zB "P" ändere:
Code:
HTMLDocument.Iterator iter = htmlDoc.getIterator(HTML.Tag.P);
erhalte ich nur noch eine "NullPointerException"! :confused:
 
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:
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:
<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:
Code:
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
 
Hallo,

Java:
/*
 * 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:
Code:
bla1
bla2
bla3
bla4
bla5
bla6
hugo.gif
hugo.gif

Gruß Tom
 
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
 
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
Code:
<div>Hallo Welt!</div>
würde ich gerne "Hallo Welt!" extrahieren.

Vielen Dank!
 
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
Code:
<div>Hallo Welt!</div>
würde ich gerne "Hallo Welt!" extrahieren.

Vielen Dank!
Hi,
ich habe die gleiche Frage wie Du. Hast Du schon eine Lösung für dein Problem?
Danke. Criss.
 
Zitat:
Zitat von Fulk
clear.gif

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
Code: <div>Hallo Welt!</div>
würde ich gerne "Hallo Welt!" extrahieren.

Vielen Dank!


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

Code:
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
 
Zuletzt bearbeitet:
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:
Code:
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.
 

Neue Beiträge

Zurück