www.www.zaachi.com »  Blog/Java  »  Java: Html parser

Java: Html parser



Html parser je program, který dokáže analyzovat HTML kód a dokáže jej rozebrat na jednotlivé části, tagy, a text.

 

Reklama

Pokud mě chcete podpořit a jste milovník jedné stopy, navštivte můj projekt: MotoArena.cz

Naprogramovat kvalitní HTML parser může být problém. Parser musí projít HTML dokument, tento dokument analyzovat a rozebrat. Určitě si dokážete představit jak je takový algoritmus složitý.

V javě existuje pro tuto problematiku již hotové řešení v podobě HTMLEditorKit.ParserCallback, který se nachází v javax.swing.text.

Použití ParserCallback si ukážeme nejlépe na příkladu.

Class ParseHtml

Naprogramujeme si třídu ParseHtml, která bude dědit HTMLEditorKit.ParserCallback adokáže analyzovat HTML kód a informace přehledně vypsat. Dokáže vypsat:

  • začátek tagu
  • konec tagu
  • atributy, které tag obsahuje
  • samostatný text
  • html poznámky
  • chyby při parsování

Metody pro všechny tyto operace jsou již v ParserCallback implementovány, takže je stačí použít.

Jako první vytvoříme konstruktor, který bude obsahovat dva vstupní parametry. Url adresu, kterou chceme parsovat a kódování, ve kterém bude html dokument načten.

V konstruktoru vytvoříme public proměnné a pro URL adresu provedeme jednouduchou kontrolu:

public class ParseHtml extends HTMLEditorKit.ParserCallback {

	public String url = null;

	public String charset = null;

	/**
	 * 
	 * @param url
	 * @param charset
	 * konstruktor tridy HtmlToText
	 */
	public ParseHtml(String url, String charset) {
		//jednoducha kontrola url adresy, jestli je ve tvaru s HTTP://
		if (this.check_url(url.trim()) == 0) {
			System.out.println("Url adresa neni ve spravnem tvaru. Prosim zadejte adresu ve tvaru http://");
			return;
		}
		
		//nastaveni promennych
		this.url = url;
		this.charset = charset;
	}

	/**
	 * 
	 * @param url
	 * @return
	 * jednoducha kontrola url adresy
	 */
	public int check_url(String url) {
		if (url.startsWith("http://") == false)
			return 0;
		return 1;
	}
}

Tím máme hotový základ, který pouze vytvoří proměnné a provede jednoducou kontrolu.

Co musíme uděla nyní je připojit se k dané URL adrese. Z url adresy si tedy vytvoříme proměnnou typu URL a nezbývá než vytvořit BufferedReader. Pro tuto operaci si vytvoříme novou metodu, jejíž volání přidáme do konstruktoru:

/**
 * zacatek parsovani. Vytvori bufferdreader a spusti parser
 */
private void run_url() {
	try {
		//vytvoreni nove URL
		URL url_id = new URL(this.url);
		//Vytvoreni BufferedReaderu
		BufferedReader htmlPage = new BufferedReader(new InputStreamReader(
				url_id.openStream(), this.charset));
		//spusteni parsovani
		this.parse(htmlPage);
	} catch (MalformedURLException e) {
		e.printStackTrace();
	} catch (UnsupportedEncodingException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}
}

Pokud je URL adresa otevřena voláme metodu parse, do které předáme jako parametr BufferedReader. Metoda parser vypadá následovně:

/**
 * 
 * @param htmlText
 * @throws IOException
 * vytvori novy ParserDelegator a vola metodu pro parsovani
 */
public void parse(Reader htmlText) throws IOException {
	ParserDelegator delegator = new ParserDelegator();
	delegator.parse(htmlText, this, Boolean.TRUE);
}

Vytvoříme nový ParserDelegator a začneme parsovat. Pro přístupu k jednotlivým informacím o HTML dokumentu nám slouží impmentované metody.

HhndleText

První z několika metod je handleText. Slouží pro odchycení textu, který se nachází mimo HTML značky. Vstupní parametry jsou zde pouze dva. Text a jeho pozice v dokumentu.

Použití může být obdobné tomuto:

/**
 * @param text
 * @param pos
 * handleText odchiti veskery text, ktery vytvari obsah html stranky
 */
public void handleText(char[] text, int pos) {
	System.out.println("Text: " + String.valueOf(text));
}

handleComment

Metoda handleComment umožňuje přístup k html komentářům. Vstupní parametry jsou obdobné jako u textu, a to text komentáře a pozice v dokumentu.

Opět jednoduché použití:

/**
 * @param coment
 * @param pos
 * handleComent odchiti html poznamky
 */
public void handleComment(char[] coment, int pos) {
	System.out.println("Komentar: " + String.valueOf(coment));
}

handleStartTag

Určitě užitečná a zajímavá metoda je handleStartTag, která dokáže informovat o začátku nového tagu a navíc dokáže odchytit i atributy, které jsou v tagu umístěny:

/**
 * @param tag
 * @param atr
 * @param pos
 * handleStartTag odchyti zacatek noveho tagu, vcetne jeho atributu
 */
public void handleStartTag(HTML.Tag tag, MutableAttributeSet atr, int pos) {
	System.out.println("Zacatek tagu: "" + tag + """);
	System.out.println("Tag obsahuje atributy: "" + atr + """);
}

handleEndTag

K metodě handleStartTag musí existovat i metoda handleEndTag, která na rozdíl od první metody dokáže zjistit ukončení tagu. Vstupní parametry jsou v tomto případě pouze dva a to HTML.Tag a pozice v dokumentu:

/**
 * @param tag
 * @param atr
 * @param pos
 * handleEndTag odchyti konec tagu
 */
public void handleEndTag(HTML.Tag tag, int pos) {
	System.out.println("Konec tagu: "" + tag + """);
}

handleSimpleTag

Metoda handleStartTag informuje pouze o přítomnosti tagu, který je párový. Neinformuje o tagu jako je například BR, IMG, HR a podobně, které párové nejsou.

Pro tuto potřebu je zde metoda handleSimpleTag. Metoda obsahuje stejně jako handleStartTag tři parametry:

/**
 * @param tag
 * @param atr
 * @param pos
 * handleSimpleTag odchyti jednoduche html tagy jako BR, IMG, apod.
 */
public void handleSimpleTag(HTML.Tag tag, MutableAttributeSet atr, int pos) {
	System.out.println("Zacatek jednoducheho tagu: "" + tag + """);
	System.out.println("Tag obsahuje atributy: "" + atr + """);
}

handleError

Pokud při parsování nastane jakýkoli problém, dokáže nás o tom informovat metoda handleError. Jako parametry jsou String ve tvaru chyby a pozice v dokumentu:

/**
 * @param str
 * @param pos
 * handleError odchyti chby v HTML
 */
public void handleError(String str, int pos) {
	//System.out.println("Parse error: " + str);
}

Výstup třídy nás dokáže podrobně informovat o celé struktuře html dokumentu:

Zacatek tagu: "h3"
Tag obsahuje atributy: "class=title s_win_title "
Zacatek tagu: "span"
Tag obsahuje atributy: "class=ico "
Zacatek jednoducheho tagu: "img"
Tag obsahuje atributy: "alt=Stream.cz - 
zábavná videa height=16 src=/favicons/194.png width=16 "
Konec tagu: "span"
Zacatek tagu: "span"
Tag obsahuje atributy: "class=text "
Zacatek tagu: "a"
Tag obsahuje atributy: "href=http://www.stream.cz 
title=Stream.cz - zábavná videa | 
Aktualizováno v 13:05 "
Text: Stream.cz - zábavná videa
Konec tagu: "a"
Konec tagu: "span"

Protože známe atributy, nebyl by problém zjistit například veškeré url adresy, které daná HTML stránka obsahuje:

public void handleStartTag(HTML.Tag tag, MutableAttributeSet a, int pos)
{
	if( String.valueOf( tag ) == "a"){
		if( String.valueOf( a ).startsWith("href=http://") )
				System.out.println( String.valueOf( a ).substring(5) );
	}
}

nebo podobným způsobem hodnoty jiných atributů.

Nakonec kód celé třídy pro parsování:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.parser.ParserDelegator;

public class ParseHtml extends HTMLEditorKit.ParserCallback {

	public String url = null;

	public String charset = null;

	/**
	 * 
	 * @param url
	 * @param charset
	 * konstruktor tridy HtmlToText
	 */
	public ParseHtml(String url, String charset) {
		//jednoducha kontrola url adresy, jestli je ve tvaru s HTTP://
		if (this.check_url(url.trim()) == 0) {
			System.out.println("Url adresa neni ve spravnem tvaru. Prosim zadejte adresu ve tvaru http://");
			return;
		}
		
		//nastaveni promennych
		this.url = url;
		this.charset = charset;
		//spusteni parseru
		run_url();
	}

	/**
	 * zacatek parsovani. Vytvori bufferdreader a spusti parser
	 */
	private void run_url() {
		try {
			//vytvoreni nove URL
			URL url_id = new URL(this.url);
			//Vytvoreni BufferedReaderu
			BufferedReader htmlPage = new BufferedReader(new InputStreamReader(
					url_id.openStream(), this.charset));
			//spusteni parsovani
			this.parse(htmlPage);
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 
	 * @param url
	 * @return
	 * jednoducha kontrola url adresy
	 */
	public int check_url(String url) {
		if (url.startsWith("http://") == false)
			return 0;
		return 1;
	}

	/**
	 * 
	 * @param htmlText
	 * @throws IOException
	 * vytvori novy ParserDelegator a vola metodu pro parsovani
	 */
	public void parse(Reader htmlText) throws IOException {
		ParserDelegator delegator = new ParserDelegator();
		delegator.parse(htmlText, this, Boolean.TRUE);
	}

/**
 * @param text
 * @param pos
 * handleText odchiti veskery text, ktery vytvari obsah html stranky
 */
public void handleText(char[] text, int pos) {
	System.out.println("Text: " + String.valueOf(text));
}

/**
 * @param coment
 * @param pos
 * handleComent odchiti html poznamky
 */
public void handleComment(char[] coment, int pos) {
	System.out.println("Komentar: " + String.valueOf(coment));
}

/**
 * @param tag
 * @param atr
 * @param pos
 * handleStartTag odchyti zacatek noveho tagu, vcetne jeho atributu
 */
public void handleStartTag(HTML.Tag tag, MutableAttributeSet atr, int pos) {
	System.out.println("Zacatek tagu: "" + tag + """);
	System.out.println("Tag obsahuje atributy: "" + atr + """);
}

/**
 * @param tag
 * @param atr
 * @param pos
 * handleEndTag odchyti konec tagu
 */
public void handleEndTag(HTML.Tag tag, int pos) {
	System.out.println("Konec tagu: "" + tag + """);
}

/**
 * @param tag
 * @param atr
 * @param pos
 * handleSimpleTag odchyti jednoduche html tagy jako BR, IMG, apod.
 */
public void handleSimpleTag(HTML.Tag tag, MutableAttributeSet atr, int pos) {
	System.out.println("Zacatek jednoducheho tagu: "" + tag + """);
	System.out.println("Tag obsahuje atributy: "" + atr + """);
}

/**
 * @param str
 * @param pos
 * handleError odchyti chby v HTML
 */
public void handleError(String str, int pos) {
	//System.out.println("Parse error: " + str);
}

	/**
	 * @author Zachar Jiří
	 * @param args
	 */
	public static void main(String[] args) {
		String charset = "UTF-8";
		String url = null;
		if (args.length > 0) {
			url = String.valueOf(args[0]);
		}
		if (args.length > 1) {
			charset = String.valueOf(args[1]);
		}
		new ParseHtml(url, charset);
	}
}

 

 


linkuj topclanky
Komentáře (1)

Autor: Zaachi
Publikováno: 3.3.2008 15:40:59


Mohlo by vás zajímat:
HTML & JavaScript: roztahovací Select [IE bug]
Vývoj aplikací pro iPhone: XML parser with NSXMLParser
Java a základy GUI
Java a základy GUI #2
TOPLIST.cz
rss coments img img img