1. ホーム
  2. java

[解決済み] 代表的なJavaのHTMLパーサーの長所と短所は何ですか?[クローズド]

2022-05-10 14:42:23

質問内容

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がお勧めです(これは、現実の世界ではしばしば必要とされます)。