Generał
Prawie wszystkie znane parsery HTML implementują W3C DOM API (część JAXP API, Java API do przetwarzania XML) i zapewniają org.w3c.dom.Document
wsparcie, które jest gotowe do bezpośredniego użycia przez JAXP API. Główne różnice można zwykle znaleźć w funkcjach danego parsera. Większość parserów jest do pewnego stopnia wybaczająca i pobłażliwa w przypadku źle sformułowanego HTML („tagsoup”), takiego jak JTidy , NekoHTML , TagSoup i HtmlCleaner . Zwykle używasz tego rodzaju parserów HTML do "porządkowania" źródła HTML (np. Zastępując HTML-valid <br>
przez XML-valid<br />
), tak abyś mógł go przechodzić "w zwykły sposób" używając W3C DOM i JAXP API.
Jedynymi, które wyskakuje są HtmlUnit i Jsoup .
HtmlUnit
HtmlUnit zapewnia całkowicie własne API, które daje możliwość programowego działania jak przeglądarka internetowa. To znaczy wprowadzanie wartości formularzy, klikanie elementów, wywoływanie JavaScript itp. To znacznie więcej niż sam parser HTML. To prawdziwa "przeglądarka internetowa bez GUI" i narzędzie do testowania jednostek HTML.
Jsoup
Jsoup zapewnia również całkowicie własne API. To daje możliwość wyboru elementów przy użyciu jQuery -Jak selektorów CSS i dostarcza API zręczny przemierzać drzewo HTML DOM, aby elementy zainteresowania.
W szczególności przechodzenie przez drzewo HTML DOM jest główną zaletą Jsoup. Ci, z którymi pracowali, org.w3c.dom.Document
wiedzą, jak piekielnie bolesne jest przechodzenie przez DOM przy użyciu funkcji gadatliwych NodeList
i Node
API. To prawda, XPath
sprawia , że życie jest łatwiejsze, ale nadal jest to kolejna krzywa uczenia się i może się okazać, że nadal będzie gadatliwa.
Oto przykład, który używa "zwykłego" parsera W3C DOM takiego jak JTidy w połączeniu z XPath w celu wyodrębnienia pierwszego akapitu twojego pytania i nazw wszystkich odpowiadających (używam XPath ponieważ bez niego kod potrzebny do zebrania interesujących informacji w przeciwnym razie urósłby 10 razy większy, bez pisania narzędzi / metod pomocniczych).
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());
}
A oto przykład, jak zrobić dokładnie to samo z 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());
}
Czy widzisz różnicę? To nie tylko mniej kodu, ale Jsoup jest również stosunkowo łatwy do zrozumienia, jeśli masz już umiarkowane doświadczenie z selektorami CSS (np. Tworząc strony internetowe i / lub używając jQuery).
Podsumowanie
Wady i zalety każdego z nich powinny być teraz wystarczająco jasne. Jeśli chcesz tylko skorzystać ze standardowego interfejsu API JAXP, aby go przejść, przejdź do pierwszej wspomnianej grupy parserów. Jest ich całkiem sporo . Który z nich należy wybrać, zależy od funkcji, które zapewnia (w jaki sposób czyszczenie HTML jest dla Ciebie łatwe? Czy są jakieś nasłuchiwacze / przechwytywacze i programy czyszczące specyficzne dla tagów?) Oraz solidność biblioteki (jak często jest aktualizowana / utrzymywana / naprawiana? ). Jeśli lubisz testować jednostkowo HTML, najlepszym rozwiązaniem jest HtmlUnit. Jeśli chcesz wyodrębnić określone dane z HTML (co jest często wymaganiem w świecie rzeczywistym), Jsoup jest najlepszym rozwiązaniem.