1. Información general
Jsoup es una biblioteca Java de código abierto que se utiliza principalmente para extraer datos de HTML. También le permite manipular y generar HTML. Tiene una línea de desarrollo constante, excelente documentación y una API fluida y flexible. Jsoup también se puede utilizar para analizar y crear XML.
En este tutorial, usaremos Spring Blog para ilustrar un ejercicio de scraping que demuestra varias características de jsoup:
- Cargando: buscar y analizar el HTML en un documento
- Filtrado: seleccionar los datos deseados en Elementos y recorrerlos
- Extracción: obtención de atributos, texto y HTML de nodos
- Modificar: agregar / editar / eliminar nodos y editar sus atributos
2. Dependencia de Maven
Para hacer uso de la biblioteca jsoup en su proyecto, agregue la dependencia a su pom.xml :
org.jsoup jsoup 1.10.2
Puede encontrar la última versión de jsoup en el repositorio de Maven Central.
3. Jsoup de un vistazo
Jsoup carga el HTML de la página y crea el árbol DOM correspondiente. Este árbol funciona de la misma manera que el DOM en un navegador, ofreciendo métodos similares a jQuery y JavaScript vanilla para seleccionar, recorrer, manipular texto / HTML / atributos y agregar / eliminar elementos.
Si se siente cómodo con los selectores del lado del cliente y el desplazamiento / manipulación DOM, encontrará jsoup muy familiar. Comprueba lo fácil que es imprimir los párrafos de una página:
Document doc = Jsoup.connect("//example.com").get(); doc.select("p").forEach(System.out::println);
Tenga en cuenta que jsoup solo interpreta HTML, no interpreta JavaScript. Por lo tanto, los cambios en el DOM que normalmente se realizarían después de que se cargue la página en un navegador habilitado para JavaScript no se verán en jsoup.
4. Cargando
La fase de carga comprende la obtención y el análisis del HTML en un documento . Jsoup garantiza el análisis de cualquier HTML, desde los más inválidos hasta los totalmente validados, como lo haría un navegador moderno. Se puede lograr cargando una cadena , un InputStream , un archivo o una URL.
Carguemos un documento desde la URL del blog de Spring:
String blogUrl = "//spring.io/blog"; Document doc = Jsoup.connect(blogUrl).get();
Observe el método get , representa una llamada HTTP GET. También puede hacer un HTTP POST con el método de publicación (o puede usar un método que reciba el tipo de método HTTP como parámetro).
Si necesita detectar códigos de estado anormales (por ejemplo, 404), debe detectar la excepción HttpStatusException :
try { Document doc404 = Jsoup.connect("//spring.io/will-not-be-found").get(); } catch (HttpStatusException ex) { //... }
A veces, la conexión debe personalizarse un poco más. Jsoup.connect (…) devuelve una conexión que le permite configurar, entre otras cosas, el agente de usuario, la referencia, el tiempo de espera de la conexión, las cookies, los datos de publicación y los encabezados:
Connection connection = Jsoup.connect(blogUrl); connection.userAgent("Mozilla"); connection.timeout(5000); connection.cookie("cookiename", "val234"); connection.cookie("cookiename", "val234"); connection.referrer("//google.com"); connection.header("headersecurity", "xyz123"); Document docCustomConn = connection.get();
Dado que la conexión sigue una interfaz fluida, puede encadenar estos métodos antes de llamar al método HTTP deseado:
Document docCustomConn = Jsoup.connect(blogUrl) .userAgent("Mozilla") .timeout(5000) .cookie("cookiename", "val234") .cookie("anothercookie", "ilovejsoup") .referrer("//google.com") .header("headersecurity", "xyz123") .get();
Puede obtener más información sobre la configuración de conexión navegando en el Javadoc correspondiente.
5. Filtrado
Ahora que tenemos el HTML convertido en un documento , es hora de navegar y encontrar lo que buscamos. Aquí es donde el parecido con jQuery / JavaScript es más evidente, ya que sus selectores y métodos de recorrido son similares.
5.1. Seleccionar
El método de selección de documentos recibe una cadena que representa el selector, utilizando la misma sintaxis de selector que en CSS o JavaScript, y recupera la lista de elementos coincidentes . Esta lista puede estar vacía pero no nula .
Echemos un vistazo a algunas selecciones usando el método de selección :
Elements links = doc.select("a"); Elements sections = doc.select("section"); Elements logo = doc.select(".spring-logo--container"); Elements pagination = doc.select("#pagination_control"); Elements divsDescendant = doc.select("header div"); Elements divsDirect = doc.select("header > div");
También puede utilizar métodos más explícitos inspirados en el DOM del navegador en lugar de la selección genérica :
Element pag = doc.getElementById("pagination_control"); Elements desktopOnly = doc.getElementsByClass("desktopOnly");
Dado que Element es una superclase de Document , puede obtener más información sobre cómo trabajar con los métodos de selección en Document y Element Javadocs.
5.2. Atravesar
Atravesar significa navegar a través del árbol DOM. Jsoup proporciona métodos que operan en el documento , en un conjunto de elementos o en un elemento específico , lo que le permite navegar a los padres, hermanos o hijos de un nodo.
Además, puede saltar a la primera, la última, y la enésima (usando un índice basado en 0) Elemento de un conjunto de elementos :
Element firstSection = sections.first(); Element lastSection = sections.last(); Element secondSection = sections.get(2); Elements allParents = firstSection.parents(); Element parent = firstSection.parent(); Elements children = firstSection.children(); Elements siblings = firstSection.siblingElements();
También puede recorrer las selecciones en iteración. De hecho, cualquier elemento del tipo Elementos se puede iterar:
sections.forEach(el -> System.out.println("section: " + el));
Puede hacer una selección restringida a una selección anterior (sub-selección):
Elements sectionParagraphs = firstSection.select(".paragraph");
6. Extracción
Ahora sabemos cómo llegar a elementos específicos, por lo que es hora de obtener su contenido, es decir, sus atributos, HTML o texto secundario.
Eche un vistazo a este ejemplo que selecciona el primer artículo del blog y obtiene su fecha, el texto de su primera sección y, finalmente, su HTML interno y externo:
Element firstArticle = doc.select("article").first(); Element timeElement = firstArticle.select("time").first(); String dateTimeOfFirstArticle = timeElement.attr("datetime"); Element sectionDiv = firstArticle.select("section div").first(); String sectionDivText = sectionDiv.text(); String articleHtml = firstArticle.html(); String outerHtml = firstArticle.outerHtml();
A continuación, se ofrecen algunos consejos para tener en cuenta al elegir y utilizar selectores:
- Confíe en la función "Ver código fuente" de su navegador y no solo en el DOM de la página, ya que podría haber cambiado (seleccionar en la consola del navegador puede producir resultados diferentes a jsoup)
- Conozca a sus selectores, ya que hay muchos y siempre es bueno haberlos visto antes; dominar los selectores lleva tiempo
- Use un patio de juegos para que los selectores experimenten con ellos (pegue un HTML de muestra allí)
- Be less dependent on page changes: aim for the smallest and least compromising selectors (e.g. prefer id. based)
7. Modifying
Modifying encompasses setting attributes, text, and HTML of elements, as well as appending and removing elements. It is done to the DOM tree previously generated by jsoup – the Document.
7.1. Setting Attributes and Inner Text/HTML
As in jQuery, the methods to set attributes, text, and HTML bear the same names but also receive the value to be set:
- attr() – sets an attribute's values (it creates the attribute if it does not exist)
- text() – sets element inner text, replacing content
- html() – sets element inner HTML, replacing content
Let's look at a quick example of these methods:
timeElement.attr("datetime", "2016-12-16 15:19:54.3"); sectionDiv.text("foo bar"); firstArticle.select("h2").html(" ");
7.2. Creating and Appending Elements
To add a new element, you need to build it first by instantiating Element. Once the Element has been built, you can append it to another Element using the appendChild method. The newly created and appended Element will be inserted at the end of the element where appendChild is called:
Element link = new Element(Tag.valueOf("a"), "") .text("Checkout this amazing website!") .attr("href", "//baeldung.com") .attr("target", "_blank"); firstArticle.appendChild(link);
7.3. Removing Elements
To remove elements, you need to select them first and run the remove method.
For example, let's remove all
doc.select("li.navbar-link").remove(); firstArticle.select("img").remove();
7.4. Converting the Modified Document to HTML
Finally, since we were changing the Document, we might want to check our work.
To do this, we can explore the Document DOM tree by selecting, traversing, and extracting using the presented methods, or we can simply extract its HTML as a String using the html() method:
String docHtml = doc.html();
The String output is a tidy HTML.
8. Conclusion
Jsoup is a great library to scrape any page. If you're using Java and don't require browser-based scraping, it's a library to take into account. It's familiar and easy to use since it makes use of the knowledge you may have on front-end development and follows good practices and design patterns.
You can learn more about scraping web pages with jsoup by studying the jsoup API and reading the jsoup cookbook.
The source code used in this tutorial can be found in the GitHub project.