SO and Google、さまざまな関係者が一貫して推奨しているいくつかのJava HTMLパーサーがあります。残念ながら、情報を見つけるのは難しいです。さまざまなライブラリの長所と短所について、これらのライブラリの比較に費やして、学んだことを共有できる人がいることを望んでいます。
私が見たものは次のとおりです。
そして、私が見逃した主要なパーサーがある場合、その長所と短所についても聞きたいです。
ありがとう!
ほぼすべての既知のHTMLパーサーは、- W3C DOM API (JAXP APIの一部、Java XML処理用のAPI)を実装し、 org.w3c.dom.Document
back。JAXPAPIで直接使用する準備ができています。主な違いは通常、問題のパーサーの機能にあります。ほとんどのパーサーは、 JTidy 、 NekoHTML 、 TagSoup および-のような、整形式でないHTML( "tagsoup")に対してある程度寛容で寛大です。 HtmlCleaner 。通常、この種のHTMLパーサーを使用して、HTMLソースを「整頓」します(たとえば、HTMLが有効な<br>
XMLで有効<br />
)、W3C DOMおよびJAXP APIを使用して「通常の方法で」トラバースできるようにします。
HtmlUnit は完全に独自のAPIを提供し、プログラムでWebブラウザーのように動作する可能性を提供します。つまりフォーム値の入力、要素のクリック、JavaScriptの呼び出しなどを行います。 HTMLパーサーだけではありません。これは、実際の「GUIレスWebブラウザー」およびHTML単体テストツールです。
Jsoup は完全に独自のAPIも提供します。 jQuery -like CSS selectors を使用して要素を選択する可能性を提供し、HTML DOMツリーを走査して目的の要素を取得するための洗練されたAPIを提供します。
特に、HTML DOMツリーのトラバースは、Jsoupの大きな強みです。 org.w3c.dom.Document
冗長な NodeList
および Node
APIを使用してDOMをトラバースすることの苦痛を知っています。確かに、 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());
}
違いがわかりますか?コードが少ないだけでなく、CSSセレクター(Webサイトの開発やjQueryの使用など)で既にある程度の経験がある場合は、Jsoupも比較的簡単に把握できます。
それぞれの長所と短所は十分に明確になったはずです。標準のJAXP APIを使用してトラバースするだけの場合は、最初に言及したパーサーのグループに進みます。かなり たくさん あります。どちらを選択するかは、提供する機能(HTMLクリーニングを簡単にする方法、リスナー/インターセプター、タグ固有のクリーナーはありますか?)とライブラリの堅牢性(更新/維持/修正の頻度)に依存します。 )。 HTMLの単体テストが必要な場合は、HtmlUnitが最適です。 HTMLから特定のデータを抽出したい場合(実際の要件であることが多い)、Jsoupが最適です。
Jericho HTMLパーサーは非常に適切に記述され、最新の状態に保たれ(パーサーの多くはそうではありません)、依存関係がなく、使いやすいことがわかりました。
リストに validator.nu HTML Parser (JavaでのHTML5解析アルゴリズムの実装)を追加します。
プラス面としては、HTML5に一致するように特別に設計されており、HTML5バリデーターの中心であるため、将来のブラウザーの解析動作を非常に高い精度で一致させる可能性が非常に高くなります。
マイナス面では、ブラウザーの従来の解析はこのように機能しません。HTML5はまだドラフトであるため、変更される可能性があります。
実際には、このような問題はあいまいなコーナーケースにのみ影響し、すべての実用的な目的で優れたパーサーです。
JavaのHTML解析ライブラリのほとんどを使用した後、@ MJBの回答に追加します。省略された大きな賛否両論があります。入力と出力でHTMLのフォーマットと不正確さを保持するパーサーです。
ドキュメントを変更するとほとんどのパーサーは、特にXMLのようなライブラリである場合、DOMの空白、コメント、および不正確さを吹き飛ばします。
Jericho は、ホワイトスペースのフォーマットとHTMLの不正確さを維持しながら、厄介なHTMLを操作できる唯一のパーサーです(ある場合)。
他の2つのオプションは HTMLCleaner と HTMLParser です。
私が開発しているクローラー/データ抽出フレームワークのために、ほとんどのパーサーをここで試しました。データ抽出作業の大部分にHTMLCleanerを使用します。これは、名前空間を使用してHTML、XHTML、HTML 5の比較的現代的な方言をサポートし、DOMをサポートしているためです Javaの組み込みXPath実装で使用 が可能です。
HTMLCleanerでこれを行うのは、他のパーサーよりもはるかに簡単です。たとえば、JSoupは、DOMではなくDOMのようなインターフェイスをサポートしているため、一部のアセンブリが必要です。 JerichoにはSAX-lineインターフェースがあるため、やはり作業が必要になります Sujit Palにはこれを行う方法の説明があります .
また、テーブル抽出タスクにHTMLParserとJerichoを使用します。これは、Perlの libhtml-tableextract-Perl を使用して記述されたコードの一部を置き換えます。 HTMLParserを使用してテーブルのHTMLをフィルターし、Jerichoを使用して解析します。 MJBとAdamのコメントには、Jerichoが基礎となるHTMLを保持しているため、場合によっては良いという意見に同意します。非標準のSAXインターフェースのようなものがあるため、XPath処理にはHTMLCleanerの方が適しています。
JavaでのHTMLの解析は、すべてのパーサーが特定の種類の不正なHTMLコンテンツで苦労しているように見えるため、驚くほど難しい問題です。