Analyse HTML en Java avec Jsoup

1. Vue d'ensemble

Jsoup est une bibliothèque Java open source utilisée principalement pour extraire des données à partir de HTML. Il vous permet également de manipuler et de générer du HTML. Il dispose d'une ligne de développement régulière, d'une excellente documentation et d'une API fluide et flexible. Jsoup peut également être utilisé pour analyser et créer du XML.

Dans ce tutoriel, nous utiliserons le blog Spring pour illustrer un exercice de scraping qui démontre plusieurs fonctionnalités de jsoup:

  • Chargement: récupération et analyse du HTML dans un document
  • Filtrage: sélectionner les données souhaitées en Eléments et les parcourir
  • Extraction: obtention des attributs, du texte et du HTML des nœuds
  • Modification: ajout / modification / suppression de nœuds et modification de leurs attributs

2. Dépendance de Maven

Pour utiliser la bibliothèque jsoup dans votre projet, ajoutez la dépendance à votre pom.xml :

 org.jsoup jsoup 1.10.2 

Vous pouvez trouver la dernière version de jsoup dans le référentiel Maven Central.

3. Jsoup en un coup d'œil

Jsoup charge le code HTML de la page et construit l'arborescence DOM correspondante. Cet arbre fonctionne de la même manière que le DOM dans un navigateur, offrant des méthodes similaires à jQuery et JavaScript vanilla pour sélectionner, parcourir, manipuler du texte / HTML / attributs et ajouter / supprimer des éléments.

Si vous êtes à l'aise avec les sélecteurs côté client et la traversée / manipulation DOM, vous trouverez jsoup très familier. Vérifiez à quel point il est facile d'imprimer les paragraphes d'une page:

Document doc = Jsoup.connect("//example.com").get(); doc.select("p").forEach(System.out::println);

Gardez à l'esprit que jsoup n'interprète que le HTML - il n'interprète pas JavaScript. Par conséquent, les modifications du DOM qui auraient normalement lieu après le chargement de la page dans un navigateur compatible JavaScript ne seront pas visibles dans jsoup.

4. Chargement

La phase de chargement comprend l'extraction et l'analyse du HTML dans un document . Jsoup garantit l'analyse de tout HTML, du plus invalide au plus totalement validé, comme le ferait un navigateur moderne. Cela peut être réalisé en chargeant une chaîne , un InputStream , un fichier ou une URL.

Chargeons un document à partir de l'URL du blog Spring:

String blogUrl = "//spring.io/blog"; Document doc = Jsoup.connect(blogUrl).get();

Notez la méthode get , elle représente un appel HTTP GET. Vous pouvez également faire un HTTP POST avec la méthode post (ou vous pouvez utiliser une méthode qui reçoit le type de méthode HTTP en tant que paramètre).

Si vous avez besoin de détecter des codes d'état anormaux (par exemple 404), vous devez intercepter l' exception HttpStatusException :

try { Document doc404 = Jsoup.connect("//spring.io/will-not-be-found").get(); } catch (HttpStatusException ex) { //... }

Parfois, la connexion doit être un peu plus personnalisée. Jsoup.connect (…) renvoie une connexion qui vous permet de définir, entre autres, l'agent utilisateur, le référent, le délai de connexion, les cookies, les données de publication et les en-têtes:

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();

Étant donné que la connexion suit une interface fluide, vous pouvez chaîner ces méthodes avant d'appeler la méthode HTTP souhaitée:

Document docCustomConn = Jsoup.connect(blogUrl) .userAgent("Mozilla") .timeout(5000) .cookie("cookiename", "val234") .cookie("anothercookie", "ilovejsoup") .referrer("//google.com") .header("headersecurity", "xyz123") .get();

Vous pouvez en savoir plus sur les paramètres de connexion en parcourant la Javadoc correspondante.

5. Filtrage

Maintenant que nous avons converti le HTML en document , il est temps de le parcourir et de trouver ce que nous recherchons. C'est là que la ressemblance avec jQuery / JavaScript est la plus évidente, car ses sélecteurs et ses méthodes de parcours sont similaires.

5.1. Sélection

La méthode de sélection de document reçoit une chaîne représentant le sélecteur, en utilisant la même syntaxe de sélecteur que dans un CSS ou JavaScript, et récupère la liste correspondante d' éléments . Cette liste peut être vide mais pas nulle .

Jetons un coup d'œil à quelques sélections en utilisant la méthode de sélection :

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");

Vous pouvez également utiliser des méthodes plus explicites inspirées du DOM du navigateur au lieu de la sélection générique :

Element pag = doc.getElementById("pagination_control"); Elements desktopOnly = doc.getElementsByClass("desktopOnly");

Comme Element est une superclasse de Document , vous pouvez en savoir plus sur l'utilisation des méthodes de sélection dans les Javadocs Document et Element .

5.2. Traverser

Traverser signifie naviguer dans l'arborescence DOM. Jsoup fournit des méthodes qui opèrent sur le document , sur un ensemble d' éléments ou sur un élément spécifique , vous permettant de naviguer vers les parents, frères et sœurs ou enfants d'un nœud.

En outre, vous pouvez accéder au premier, au dernier et au nième élément (à l'aide d'un index basé sur 0) dans un ensemble d' éléments :

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();

Vous pouvez également parcourir les sélections. En fait, tout élément de type Elements peut être itéré:

sections.forEach(el -> System.out.println("section: " + el));

Vous pouvez faire une sélection restreinte à une sélection précédente (sous-sélection):

Elements sectionParagraphs = firstSection.select(".paragraph");

6. Extraction

Nous savons maintenant comment atteindre des éléments spécifiques, il est donc temps d'obtenir leur contenu - à savoir leurs attributs, HTML ou texte enfant.

Jetez un œil à cet exemple qui sélectionne le premier article du blog et obtient sa date, son premier texte de section, et enfin, son HTML interne et externe:

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();

Voici quelques conseils à garder à l'esprit lors du choix et de l'utilisation des sélecteurs:

  • Fiez-vous à la fonctionnalité «Afficher la source» de votre navigateur et pas seulement sur la page DOM car elle a pu changer (la sélection dans la console du navigateur peut donner des résultats différents de jsoup)
  • Connaissez vos sélecteurs car il y en a beaucoup et il est toujours bon de les avoir au moins vus auparavant; la maîtrise des sélecteurs prend du temps
  • Utilisez un terrain de jeu pour que les sélecteurs les expérimentent (collez-y un exemple de HTML)
  • Soyez moins dépendant des changements de page: visez les sélecteurs les plus petits et les moins compromettants (par exemple, préférez les ID)

7. Modification

La modification englobe la définition des attributs, du texte et du code HTML des éléments, ainsi que l'ajout et la suppression d'éléments. Cela se fait dans l'arborescence DOM précédemment générée par jsoup - le Document .

7.1. Définition des attributs et du texte intérieur / HTML

Comme dans jQuery, les méthodes pour définir les attributs, le texte et le HTML portent les mêmes noms mais reçoivent également la valeur à définir:

  • attr () - définit les valeurs d'un attribut (il crée l'attribut s'il n'existe pas)
  • text () - définit le texte intérieur de l'élément, remplaçant le contenu
  • html () - définit le HTML interne de l'élément, remplaçant le contenu

Regardons un exemple rapide de ces méthodes:

timeElement.attr("datetime", "2016-12-16 15:19:54.3"); sectionDiv.text("foo bar"); firstArticle.select("h2").html(" "); 

7.2. Création et ajout d'éléments

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

  • tags that contain the “navbar-link” class from Document, and all images from the first article:

    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.