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.
Jsoup
jest dobry. Próbowałem połączyć go z innym modułem, który współpracuje zorg.w3c.dom.*
API. Okazało się, że Jsoup nie przestrzegaorg.w3c.dom.*
kontraktuW tym artykule porównano niektóre aspekty następujących parserów:
W żadnym wypadku nie jest to pełne podsumowanie i pochodzi z 2008 roku. Może się jednak okazać pomocne.
źródło
Dodaj analizator HTML validator.nu do listy analizator , implementację algorytmu parsowania HTML5 w Javie.
Z drugiej strony, jest specjalnie zaprojektowany, aby dopasować się do HTML5 i jest sercem walidatora HTML5, więc jest bardzo prawdopodobne, że będzie pasował do przyszłego zachowania parsowania przeglądarki z bardzo wysokim stopniem dokładności.
Z drugiej strony, żadna ze starszych przeglądarek nie działa dokładnie w ten sposób, a ponieważ HTML5 jest nadal w wersji roboczej, może ulec zmianie.
W praktyce takie problemy dotyczą tylko niejasnych przypadków narożnych i ze względów praktycznych są doskonałym parserem.
źródło
Zauważyłem, że Jericho HTML Parser jest bardzo dobrze napisany, aktualizowany (co nie jest dla wielu parserów), nie zawiera żadnych zależności i jest łatwy w użyciu.
źródło
Po prostu dodam do odpowiedzi @MJB po pracy z większością bibliotek parsujących HTML w Javie, jest ogromna zaleta / wada, która jest pomijana: parsery, które zachowują formatowanie i niepoprawność HTML na wejściu i wyjściu.
To jest większość parserów, kiedy zmieniasz dokument, usunie spacje, komentarze i niepoprawność DOM, szczególnie jeśli są to biblioteki podobne do XML.
Jericho to jedyny parser, jaki znam, który pozwala na manipulowanie nieprzyjemnym kodem HTML, zachowując jednocześnie formatowanie białych znaków i niepoprawność HTML (jeśli istnieje).
źródło
Dwie inne opcje to HTMLCleaner i HTMLParser .
Wypróbowałem większość parserów tutaj dla platformy przeszukiwacza / wyodrębniania danych, którą opracowałem. Używam HTMLCleaner do większości prac związanych z wyodrębnianiem danych. Dzieje się tak, ponieważ obsługuje dość nowoczesny dialekt HTML, XHTML, HTML 5 z przestrzeniami nazw i obsługuje DOM, więc można go używać z wbudowaną implementacją Javy w XPath .
Dużo łatwiej jest to zrobić z HTMLCleaner niż niektórymi innymi parserami: na przykład JSoup obsługuje interfejs podobny do DOM, a nie DOM, więc wymagany jest pewien montaż . Jericho ma interfejs linii SAX, więc znowu wymaga to trochę pracy, chociaż Sujit Pal ma dobry opis, jak to zrobić, ale ostatecznie HTMLCleaner po prostu działał lepiej.
Używam również HTMLParser i Jericho do zadania ekstrakcji tabeli, które zastąpiło kod napisany przy użyciu libhtml-tableextract-perl Perla . Używam HTMLParser do filtrowania kodu HTML dla tabeli, a następnie używam Jericho, aby go przeanalizować. Zgadzam się z komentarzami MJB i Adama, że Jericho jest dobre w niektórych przypadkach, ponieważ zachowuje podstawowy HTML. Ma rodzaj niestandardowego interfejsu SAX, więc do przetwarzania XPath lepiej jest HTMLCleaner.
Przetwarzanie kodu HTML w Javie jest zaskakująco trudnym problemem, ponieważ wydaje się, że wszystkie parsery mają problemy z niektórymi typami źle sformatowanej zawartości HTML.
źródło