HTMLをパースする際、サードパーティのライブラリを利用したHTMLのパース方法はいくつか存在するが、 ここでは、JavaAPIを利用してHTMLをパースする方法を紹介したい。 今回HTMLパースに利用するJavaAPIは、ParserDelegatorというクラスである。 このクラスは、javax.swing.text.html.parserパッケージに同梱されている。 詳しくは、 ParserDelegatorのjavadoc を参照して欲しい。
ParserDelegatorに関連するクラスは、以下の通りである。
HTMLのパースに関連するクラス
- javax.swing.text.html.parser.ParserDelegator
- javax.swing.text.MutableAttributeSet
- javax.swing.text.html.HTML
- javax.swing.text.html.HTMLEditorKit
- javax.swing.text.html.HTML.Tag
- javax.swing.text.html.HTMLEditorKit.ParserCallback
今回は、下記のHTMLファイル(file.html)をパースし、inputタグだけを抽出し、inputタグのname属性とvalue属性をListに詰め込み、 詰め込まれたListの中身を標準出力するという、とても単純なサンプルプログラムを書いてみる。
file.html
<html>
<p>aaaaaaaaaaa</p>
<form name="form1" action="hogeAction">
<p>ここからformです。</p>
<input name="text1" type="text" value="value1" />
<input name="text2" type="text" value="value2" />
<input name="hidden1" type="hidden" value="value3" />
<input name="hidden2" type="hidden" value="value4" />
<input name="submit1" type="submit" value="value5" />
<input name="submit2" type="submit" value="value6" />
<p>ここまでformです。</p>
</form>
<a href="aaa.html">bbbbbb</a>
<p>ccccccc<p>
</html>
上記のHTMLをパースするJavaのソースコードは以下のようになる。
HtmlParserExample.java
package net.inuwasi.example.htmlparser;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.HTML.Tag;
import javax.swing.text.html.HTMLEditorKit.ParserCallback;
import javax.swing.text.html.parser.ParserDelegator;
/**
* HTMLをパースするExample
* <p>
* {@link ParserDelegator} と {@link HTMLEditorKit.ParserCallback}
* を利用してHTMLをパースするExampleです。<br>
* このExampleでは、file.htmlというhtmlファイルを読み込み、htmlを解析し、
* formタグ内のinputタグのnameとvalueをMapに詰め込みます。
* </p>
*
* @author admin@inuwasi.net
*/
public class HtmlParserExample {
/** formタグ開始フラグ */
private boolean startFormTag = false;
/** inputタグのnameとvalueを格納するためのリスト */
private List<String> list = new ArrayList<String>();
public static void main(String[] args) throws Exception {
new HtmlParserExample();
}
public HtmlParserExample() throws IOException {
// file.htmlを読み込みます。
BufferedReader reader = new BufferedReader(new FileReader("file.html"));
// パーサーコールバック作成
ParserCallback parserCallback = new HTMLEditorKit.ParserCallback() {
/**
* @see javax.swing.text.html.HTMLEditorKit.ParserCallback#handleText(char[],
* int)
*/
@Override
public void handleText(char[] data, int pos) {
super.handleText(data, pos);
// テキストがdataに入ってきます。
// 例えば、"<p>ホゲ</p>" のようなタグがあった場合、"ホゲ" の部分がテキストにあたります。
System.out.println("data=" + new String(data));
}
/**
* @see javax.swing.text.html.HTMLEditorKit.ParserCallback#handleSimpleTag(javax.swing.text.html.HTML.Tag,
* javax.swing.text.MutableAttributeSet, int)
*/
@Override
public void handleSimpleTag(Tag t, MutableAttributeSet a, int pos) {
super.handleSimpleTag(t, a, pos);
// formタグが開始されていなければ処理を抜ける
if (!startFormTag) {
return;
}
// inputタグのnameとvalueを取得
if (t.equals(Tag.INPUT)) {
String name = (String) a.getAttribute(HTML.Attribute.NAME); // name属性を取得
String value = (String) a
.getAttribute(HTML.Attribute.VALUE); // value属性を取得
System.out.println("name=" + name + ", value=" + value);
// "name=value" の形式でリストに追加
list.add(name + "=" + value);
}
}
/**
* @see javax.swing.text.html.HTMLEditorKit.ParserCallback#handleStartTag(javax.swing.text.html.HTML.Tag,
* javax.swing.text.MutableAttributeSet, int)
*/
@Override
public void handleStartTag(Tag t, MutableAttributeSet a, int pos) {
super.handleStartTag(t, a, pos);
// formタグかどうかを判断
if (t.equals(Tag.FORM)) {
System.out.println("formタグが開始しました。");
startFormTag = true;
}
}
/**
* @see javax.swing.text.html.HTMLEditorKit.ParserCallback#handleEndTag(javax.swing.text.html.HTML.Tag,
* int)
*/
@Override
public void handleEndTag(Tag t, int pos) {
super.handleEndTag(t, pos);
// formタグかどうかを判断
if (t.equals(Tag.FORM)) {
System.out.println("formタグが終了しました。");
startFormTag = false;
}
}
};
// パーサーデリゲータ作成
ParserDelegator parserDelegator = new ParserDelegator();
// htmlをパースします。
parserDelegator.parse(reader, parserCallback, false);
// 出力してみる。
System.out.println("listの中身を出力⇒ " + list.toString());
}
}
上記のクラスを実行すると以下のように標準出力される。
data=aaaaaaaaaaa
formタグが開始しました。
data=ここからformです。
name=text1, value=value1
name=text2, value=value2
name=hidden1, value=value3
name=hidden2, value=value4
name=submit1, value=value5
name=submit2, value=value6
data=ここまでformです。
formタグが終了しました。
data=bbbbbb
data=ccccccc
listの中身を出力⇒ [text1=value1, text2=value2, hidden1=value3, hidden2=value4, submit1=value5, submit2=value6]
コードの解説
HTMLEditorKit.ParserCallbackをオーバーライド実装している部分が今回の肝となる。 handleStartTagメソッドでformタグの開始を判断し、 handleEndTagメソッドで、formタグの終了を判断している。 handleSimpleTagメソッドの中では、現在読み込まれているタグを評価し、それがinputタグであれば、 そのinputタグのname属性とvalue属性を取得し、結果表示用のリストへ格納している。 ParserCallbackが実装できたら、file.htmlを読み込んだInputStreamと、先ほどのParserCallback実装のインスタンスを parserDelegator#parse に渡し、 HTMLのパースを実行している。 そして最後は、結果表示用のリストを標準出力している。
このように、JavaAPIであるParserDelegatorとHTMLEditorKit.ParserCallbackを利用すれば、面倒なHTMLパース処理も割と簡単に実現できるのである。
お薦めのJava本
ピアソンエデュケーション
売り上げランキング: 4859

正しいプログラミングを学べる
読んで、理解して、実践できれば、一人前
中級以上なら必須のマナー
Javaの良書作成日
2009-01-05
更新日
2009-01-05

