回答:
ほとんどすべての既知のHTMLパーサーはW3C DOM API(JAXP API、XML処理用Java APIの一部)を実装しており、JAXP APIでorg.w3c.dom.Document
直接使用できる状態になっています。主な違いは通常、問題のパーサーの機能にあります。ほとんどのパーサはのような非整形式HTMLとある程度の寛容と寛大(「tagsoup」)にあるJTidy、NekoHTML、TagSoupとHtmlCleaner。通常、この種のHTMLパーサーを使用してHTMLソースを「整頓」します(たとえば、HTML-valid <br>
をXML-validで置き換える<br />
)ため、W3C DOMおよびJAXP APIを使用して「通常の方法」でトラバースできます。
HtmlUnitは完全に独自のAPIを提供し、プログラムでWebブラウザーのように動作する可能性を提供します。つまり、フォーム値の入力、要素のクリック、JavaScriptの呼び出しなどです。HTMLパーサーだけではありません。これは、実際の「GUIを使用しないWebブラウザー」およびHTML単体テストツールです。
Jsoupは完全に独自のAPIも提供します。jQueryのようなCSSセレクターを使用して要素を選択する可能性を提供し、HTML DOMツリーを走査して目的の要素を取得するための洗練されたAPIを提供します。
特にHTML DOMツリーのトラバースは、Jsoupの主要な強みです。これまでに作業を行った人はorg.w3c.dom.Document
、詳細NodeList
とNode
API を使用してDOMをトラバースするのは大変なことです。確かにXPath
、生活を楽にしますが、それでも、それは別の学習曲線であり、それでもまだ冗長になる可能性があります。
これは、JTidyのような「プレーンな」W3C DOMパーサーをXPathと組み合わせて使用して、質問の最初の段落とすべての回答者の名前を抽出する例です(私は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());
}
違いがわかりますか?これはコードが少ないだけでなく、CSSセレクター(Webサイトの開発やjQueryの使用など)の経験がすでにあれば、Jsoupも比較的簡単に理解できます。
それぞれの長所と短所は十分に明確になっているはずです。標準のJAXP APIを使用してトラバースするだけの場合は、最初に言及したパーサーのグループに進みます。かなりたくさんあります。どちらを選択するかは、提供する機能(HTMLクリーニングがどのように簡単になるか?リスナー/インターセプターとタグ固有のクリーナーがあるか?)とライブラリーの堅牢性(どのくらいの頻度で更新/保守/修正するか)によって異なります。 )。HTMLの単体テストを行う場合は、HtmlUnitが適しています。HTMLから特定のデータを抽出したい場合(これは現実の要件ではありがちですが)、Jsoupが適しています。
Jsoup
いいね。org.w3c.dom.*
API で動作する別のモジュールとのインターフェースを試みました。Jsoupがorg.w3c.dom.*
契約に従わないことが判明
この記事では、以下のパーサーの特定の側面を比較します。
それは決して完全な要約ではなく、2008年のものです。しかし、あなたはそれが役に立つと思うかもしれません。
追加validator.nu HTMLパーサあなたのリストに、JavaでHTML5の構文解析アルゴリズムの実装を。
プラス面としては、HTML5に一致するように特別に設計されており、HTML5バリデーターの中心にあるため、将来のブラウザーの解析動作を非常に高い精度で一致させる可能性が非常に高くなります。
マイナス面としては、ブラウザーの従来の構文解析がこれとまったく同じように機能することはなく、HTML5はまだドラフトであり、変更される可能性があります。
実際には、このような問題はあいまいなコーナーケースにのみ影響し、あらゆる実用的な目的のために優れたパーサーです。
他の2つのオプションは、HTMLCleanerとHTMLParserです。
私が開発しているクローラー/データ抽出フレームワークのために、ここでほとんどのパーサーを試しました。データ抽出作業の大部分にHTMLCleanerを使用しています。これは、ネームスペースを備えた、HTML、XHTML、HTML 5の合理的に現代的な方言をサポートし、DOMをサポートするため、Javaの組み込みXPath実装で使用できるためです。
HTMLCleanerを使用すると、他のパーサーよりもはるかに簡単にこれを実行できます。たとえば、JSoopは、DOMではなくDOMのようなインターフェイスをサポートしているため、いくつかのアセンブリが必要です。JerichoはSAXラインインターフェイスを備えているので、これも多少の作業が必要ですが、Sujit Palがこれを行う方法についてはよく説明していますが、最終的にはHTMLCleanerの方が優れています。
また、HTMLParserとJerichoをテーブル抽出タスクに使用しています。これは、Perlのlibhtml-tableextract-perlを使用して記述されたコードの一部を置き換えました。HTMLParserを使用してテーブルのHTMLをフィルター処理し、次にJerichoを使用してそれを解析します。MJBとAdamのコメントに同意します。Jerichoは、基盤となるHTMLを保持するため、場合によっては優れています。ある種の非標準のSAXインターフェースを備えているため、XPath処理にはHTMLCleanerの方が優れています。
JavaでのHTMLの解析は、すべてのパーサーが特定のタイプの不正なHTMLコンテンツに苦労しているように見えるため、驚くほど難しい問題です。