[解決済み] 代表的なJavaのHTMLパーサーの長所と短所は何ですか?[クローズド]
質問内容
SOやGoogleで検索してみると、各方面から一貫して推奨されているJavaのHTMLパーサーがいくつかあることがわかりました。残念ながら、様々なライブラリの長所と短所に関する情報を見つけることは困難です。これらのライブラリを比較したことのある人がいて、彼らが学んだことを共有できることを期待しています。
以下は、その内容です。
また、私が見逃している主要なパーサーがあれば、その長所と短所もぜひ教えてください。
ありがとうございました。
解決方法は?
一般
ほとんどすべての既知の HTML パーサーは
W3C DOM API
(JAXP API, Java API for XML processingの一部)を使用し、その上で
org.w3c.dom.Document
JAXP APIで直接使用できるようになります。大きな違いは、通常、問題のパーサの機能にあります。ほとんどのパーサーは、以下のような非整形のHTML("tagsoup")に対してある程度寛容で甘やかされています。
JTidy
,
NekoHTML
,
タグスープ
と
HtmlCleaner
. 通常、この種の HTML パーサーは、HTML ソースを整頓するために使用します(例えば、HTML Valid な
<br>
をXML Validな
<br />
W3CのDOMとJAXPのAPIを使って、通常の方法でトラバースできるようにするためです。
唯一飛びぬけているのは HtmlUnit と Jsoup .
HtmlUnit
HtmlUnit は、完全に独自の API を提供し、プログラム的にウェブブラウザのように動作させる可能性を与えます。例えば、フォームの値を入力したり、要素をクリックしたり、JavaScriptを呼び出したり、などなど。これは、単なるHTMLパーサーをはるかに超えるものです。GUIレスのウェブブラウザであり、HTMLユニットテストツールなのです。
Jsoup
Jsoup は、完全に独自のAPIを提供している。これは jQuery -のように CSSセレクタ で、HTML DOM ツリーを走査して目的の要素を取得するための洗練された API を提供します。
特にHTML DOMツリーのトラバースは、Jsoupの大きな強みです。Jsoupを使ったことがある人なら
org.w3c.dom.Document
を使って DOM を横断するのがどれほど大変なことか、ご存じでしょう。
NodeList
と
Node
のAPIです。真の
XPath
を使えば簡単ですが、それでも、また別の学習曲線が必要で、結局は冗長になってしまいます。
ここでは、質問の最初の段落とすべての回答者の名前を抽出するために、XPathと組み合わせたJTidyのようなW3C DOMパーサーを使用する例を示します(XPathを使用しているのは、それがなければ、関心のある情報を収集するために必要なコードは、ユーティリティ/ヘルパーメソッドを書かずに10倍の大きさに膨れ上がるからです)。
String url = "http://stackoverflow.com/questions/3152138";
Document document = new Tidy().parseDOM(new URL(url).openStream(), null);
XPath xpath = XPathFactory.newInstance().newXPath();
Node question = (Node) xpath.compile("//*[@id='question']//*[contains(@class,'post-text')]//p[1]").evaluate(document, XPathConstants.NODE);
System.out.println("Question: " + question.getFirstChild().getNodeValue());
NodeList answerers = (NodeList) xpath.compile("//*[@id='answers']//*[contains(@class,'user-details')]//a[1]").evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < answerers.getLength(); i++) {
System.out.println("Answerer: " + answerers.item(i).getFirstChild().getNodeValue());
}
そして、Jsoupで全く同じことを行う例を示します。
String url = "http://stackoverflow.com/questions/3152138";
Document document = Jsoup.connect(url).get();
Element question = document.select("#question .post-text p").first();
System.out.println("Question: " + question.text());
Elements answerers = document.select("#answers .user-details a");
for (Element answerer : answerers) {
System.out.println("Answerer: " + answerer.text());
}
違いがお分かりになりますか?コードが少ないだけでなく、JsoupはCSSセレクタの経験がある人なら比較的簡単に理解できます(Webサイトの開発やjQueryの使用など)。
概要
それぞれの長所と短所は、もう十分に明らかになったはずです。標準のJAXP APIを使ってトラバースしたいだけなら、最初に述べたパーサーのグループを選ぶとよいでしょう。かなり たくさん のものです。どれを選ぶかは、そのライブラリが提供する機能(どのようにHTMLのクリーニングを容易にしているか、リスナーやインターセプター、タグ固有のクリーナーなどがあるか)とライブラリの堅牢性(更新/メンテナンス/修正の頻度はどうか)に依存します。もしあなたがHTMLをユニットテストするのが好きなら、HtmlUnitがおすすめです。もし、HTMLから特定のデータを抽出したいのであれば、Jsoupがお勧めです(これは、現実の世界ではしばしば必要とされます)。
関連
-
[解決済み] JVM起動時のパラメータ「-Xms」「-Xmx」とは何ですか?
-
スレッド "main" で例外発生 java.lang.ArrayIndexOutOfBoundsException: 0 at One1.main(One1.java:3)
-
スレッド "main" で例外発生 java.net.BindException: アドレスは既に使用中です。NET_Bind
-
起動時にEclipseエラーが発生しました。起動中に内部エラーが発生しました。java.lang.NullPoin: "Javaツーリングの初期化 "中に内部エラーが発生しました。
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Javaにおけるpublic、protected、package-private、privateの違いは何ですか?
-
[解決済み] HTMLのid属性に有効な値は何ですか?
-
[解決済み] HTMLの "role "属性は何のためにあるのですか?
-
[解決済み] Javaクラスにおけるcanonical name、simple name、class nameの違いは何ですか?
-
[解決済み] JDKとJREの違いは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Java Error スレッド "AWT-EventQueue-0" で例外発生 java.lang.
-
[解決済み] 文字列からHTMLタグを削除する
-
Spring Boot による HTTPS アクセスの設定
-
javaで非静的な解を静的な参照にすることができない
-
VMの初期化中にエラーが発生しました java/lang/NoClassDefFoundError: java/lang/Object
-
スレッド "main" での例外 java.lang.ArrayIndexOutOfBoundsException: 1
-
org.glassfish.jersey.servlet.ServletContainer
-
java 例外。Javaツールの初期化
-
ブラウザでの大容量ファイルスライスアップロード(Javaサーバサイド実装)
-
[解決済み] java.net.URLConnectionを使用してHTTPリクエストを発生させ処理する方法