人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

Javaに関する質問です。
URIが文字列で与えられてそのURIが指すHTMLのtitleタグの情報を取得したいです。
# 要は「はてな」の回答フォームみたいなもんです。
Xercesのorg.w3c.dom.html.HTMLDocument#getTitle()でうまくいくのかと思いましたがそもそもHTMLDocumentの取得の仕方がよくわかりませんでした。
HttpURLConnectionを使ってがりがり処理する方法もありますがいまひとつスマートではありません。
そこで、以下のいずれかをご教授ください。

1.URIの文字列からHTMLDocumentの取得の仕方
2.HTMLDocumentはステータスコード3xxに対応(自動的にリダイレクト)しているか。(1がわかれば自分で試します。)
3.HTMLDocument以外で実現する方法(3xxに対応必須)

とりたいのはtitleタグだけです。
より高速な方法がうれしいです。

●質問者: esseesse
●カテゴリ:コンピュータ
✍キーワード:DOM HTML Java URI W3C
○ 状態 :終了
└ 回答数 : 4/4件

▽最新の回答へ

1 ● afternoontea
●20ポイント

http://www.w3c.org/

World Wide Web Consortium

3番の方法です。w3cからw3へ301になると思います。

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

DocumentBuilder builder = factory.newDocumentBuilder();

Document document = builder.parse(”

http://www.w3c.org/

World Wide Web Consortium

”);

NodeList nodes = document.getElementsByTagName(”title”);

System.out.println(nodes.item(0).getFirstChild().getNodeValue());

◎質問者からの返答

ありがとうございます。

が、

これって、w3cはうまくいったんですが、www.yahoo.co.jpとかwww.google.co.jpはうまくいかないんです。

# 実はサンプルURIをyahooにしていたのでうまくできなくて悩んでいたのです。。。

参考までに、出てきた例外は

www.yahoo.co.jpの場合

java.io.UTFDataFormatException: Invalid byte 1 of 1-byte UTF-8 sequence.

at org.apache.xerces.impl.io.UTF8Reader.invalidByte(Unknown Source)

at org.apache.xerces.impl.io.UTF8Reader.read(Unknown Source)

at org.apache.xerces.impl.XMLEntityScanner.load(Unknown Source)

at org.apache.xerces.impl.XMLEntityScanner.scanData(Unknown Source)

at org.apache.xerces.impl.XMLScanner.scanComment(Unknown Source)

at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanComment(Unknown Source)

at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)

at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)

at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)

at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)

at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)

at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)

at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)

at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:124)

at html.HtmlTest.main(HtmlTest.java:21)

Exception in thread ”main”

www.google.co.jpの場合

[Fatal Error] :12:3: The element type ”meta” must be terminated by the matching end-tag ”</meta>”.

org.xml.sax.SAXParseException: The element type ”meta” must be terminated by the matching end-tag ”</meta>”.

at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)

at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)

at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:124)

at html.HtmlTest.main(HtmlTest.java:21)

Exception in thread ”main”

どちらも出力したHTMLの問題のような気もしますが、できればより柔軟に対応できるようにしたいです。

# この方法って

とかの閉じなくても通っちゃうタグがあるとNGになっちゃいますよね。。。


2 ● pandanaotan
●20ポイント

http://htmlparser.sourceforge.net/

HTML Parser - HTML Parser

Xercesにこだわらないのであれば、こちらのHTMLParserを使うというのも良いのではないでしょうか?多少崩れたHTMLでもParseできると思います。

◎質問者からの返答

確かにうまくparseできたのですが、parseの出力がしょぼいですね。

parseが標準出力限定(parseメソッド内でSystem.out.printlnをしている)なので、後の処理に使えないんですよね。。。

# GPLなんで修正してもいいんですが。

似たようなツール(もう少しツールとして完成されているもの)で他のものはないでしょうか。

ちなみに、Xercesには全然こだわっていません。


3 ● afternoontea
●30ポイント

http://venus.aez.jp/uploda/dat/upload10389.txt

タグが消されるようなのでアップローダーにソースを置きました。

やっていることは、

1.HttpClientでドキュメントを持ってくる

2.1行ずつ処理して正規表現でtitleタグをさがす

このやり方ならテキスト処理なので柔軟性は確保できると思います。

ただ、なんとなく大げさなのとHttpClientが別ホストへのリダイレクト(w3cからw3など)をサポートしていないという問題が残ります。

◎質問者からの返答

うーん、力技でもいいんですが、

<title></p> <p> タイトル</p> <p> </title>

とかなっていたりとかさまざまなパターンを考えて実装するよりは既存ツールのほうが完成されていていいかな、と思ったわけです。

# 個人で利用するとはいえ、単体テストとかもやらないといけないわけですし。

もちろん、最後の手段として力技は考えていますので、そのときは参考にさせてもらいます。

ありがとうございます。


4 ● pandanaotan
●40ポイント

http://www.apache.org/~andyc/neko/doc/html/

NekoHTML

CyberNeko HTML ParserとXPathを使って書いてみました。

<pre>

import java.io.*;

import java.net.*;

import org.apache.xpath.XPathAPI;

import org.cyberneko.html.parsers.DOMParser;

import org.w3c.dom.*;

import org.xml.sax.InputSource;

public class GetTitle {

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

URL url = new URL(args[0]);

URLConnection con = url.openConnection();

BufferedReader br = new BufferedReader(

new InputStreamReader(con.getInputStream(),”JISAutoDetect”));

String tmp;

StringBuffer html = new StringBuffer();

while ((tmp = br.readLine()) != null) {

html.append(tmp);

}

br.close();

try {

DOMParser parser = new DOMParser();

StringReader sr = new StringReader(html.toString());

parser.parse(new InputSource(sr));

Node node = parser.getDocument();

NodeList list = XPathAPI.selectNodeList(node, ”//TITLE”);

if ( list == null || list.getLength() == 0) {

System.out.println(”Pattern Not Found.”);

return;

}

for( int i=0; i<list.getLength(); i++ ) {

Node n = list.item( i );

System.out.println( n.getNodeName() );

Node child = n.getFirstChild();

String value = child.getNodeValue();

System.out.println( value );

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

</pre>

◎質問者からの返答

ありがとうございます、少し変更して解決しました。

変更内容は以下です。

・URLConnectionをHttpURLConnectionにキャスト

・HttpURLConnection#setFollowRedirects(boolean)でリダイレクトに対応

・parser.getDocument()をorg.w3c.doc.html.HTMLDocumentにキャスト

・HTMLDocument#getTitle()でタイトル取得

URL→StringBuffer→InputSourceの流れも省略できればベストなんですが、そこは妥協点なんですかね。。。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ