ทั่วไป
ตัวแยกวิเคราะห์ HTML ที่รู้จักกันเกือบทั้งหมดใช้W3C DOM API (ส่วนหนึ่งของ JAXP API, Java API สำหรับการประมวลผล XML) และให้การorg.w3c.dom.Document
สนับสนุนที่พร้อมใช้งานโดยตรงโดย JAXP API ความแตกต่างที่สำคัญมักจะพบได้ในคุณสมบัติของ parser ที่เป็นปัญหา parsers ส่วนใหญ่อยู่กับการให้อภัยในระดับหนึ่งและผ่อนปรนกับไม่ใช่ wellformed HTML ( "tagsoup") เช่นJTidy , NekoHTML , TagSoupและHtmlCleaner คุณมักจะใช้โปรแกรมแยกวิเคราะห์ HTML ประเภทนี้เพื่อ "จัดระเบียบ" ซอร์ส HTML (เช่นแทนที่ HTML- ใช้ได้<br>
โดยใช้ XML ได้<br />
) เพื่อให้คุณสามารถสำรวจ "วิธีปกติ" โดยใช้ W3C DOM และ JAXP API
คนเดียวที่กระโดดออกมาเป็นHtmlUnitและJsoup
HtmlUnit
HtmlUnitให้ API ของตัวเองอย่างสมบูรณ์ซึ่งช่วยให้คุณสามารถทำตัวเหมือนเว็บเบราว์เซอร์แบบเป็นโปรแกรม เช่นป้อนค่าแบบฟอร์มองค์ประกอบคลิกเรียกใช้ JavaScript และอื่น ๆ มันเป็นตัวแยกวิเคราะห์ HTML มากกว่าอย่างเดียว เป็นเครื่องมือทดสอบเว็บเบราเซอร์ GUI น้อยกว่าและ HTML
Jsoup
Jsoupยังมี API ของตัวเองอย่างสมบูรณ์ มันทำให้คุณมีความเป็นไปได้ในการเลือกองค์ประกอบโดยใช้ตัวเลือก CSS ที่เหมือนกันของjQueryและมี API ที่ลื่นไหลเพื่อสำรวจทรี HTML DOM เพื่อรับองค์ประกอบที่น่าสนใจ
โดยเฉพาะอย่างยิ่งการข้ามผ่านของโครงสร้าง HTML DOM เป็นจุดแข็งหลักของ Jsoup คนที่ได้ทำงานด้วยorg.w3c.dom.Document
รู้ว่ามันเจ็บปวดอะไรบ้างที่จะสำรวจ DOM โดยใช้ verbose NodeList
และNode
API จริงXPath
ทำให้ชีวิตง่ายขึ้น แต่ถึงกระนั้นก็เป็นอีกหนึ่งช่วงการเรียนรู้และสามารถจบลงด้วยการพูดอย่างละเอียด
นี่คือตัวอย่างที่ใช้ตัวแยกวิเคราะห์ DOM "ธรรมดา" W3C เช่น JTidy ร่วมกับ 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());
}
คุณเห็นความแตกต่างหรือไม่ มันไม่ได้เป็นเพียงรหัสน้อยกว่า แต่ Jsoup ยังเข้าใจง่ายหากคุณมีประสบการณ์ปานกลางกับตัวเลือก CSS (เช่นการพัฒนาเว็บไซต์และ / หรือการใช้ jQuery)
สรุป
ข้อดีและข้อเสียของแต่ละคนควรชัดเจนเพียงพอแล้ว หากคุณเพียงต้องการใช้ JAXP API มาตรฐานเพื่อสำรวจมันให้ไปที่กลุ่มตัวแยกวิเคราะห์ที่กล่าวถึงครั้งแรก มีสวยมากของพวกเขา ตัวเลือกใดที่จะเลือกขึ้นอยู่กับคุณลักษณะที่มีให้ (การล้าง HTML ทำได้ง่ายสำหรับคุณมีผู้ฟัง / ตัวดักจับและตัวทำความสะอาดแท็กเฉพาะหรือไม่) และความทนทานของไลบรารี (ปรับปรุงบ่อยครั้ง / แก้ไข / คงที่บ่อยแค่ไหน) ) หากคุณต้องการทดสอบหน่วย HTML แล้ว HtmlUnit เป็นวิธีที่จะไป หากคุณต้องการดึงข้อมูลเฉพาะจาก HTML (ซึ่งมากกว่าความต้องการของโลกแห่งความเป็นจริง) Jsoup เป็นวิธีที่จะดำเนินการ