Analyse HTML en Java avec Jsoup

Analyser 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 possède une ligne de développement constante, une excellente documentation et une API fluide et flexible. Jsoup peut également être utilisé pour analyser et construire du XML.

Dans ce didacticiel, nous utiliserons lesSpring Blog pour illustrer un exercice de scraping qui démontre plusieurs fonctionnalités de jsoup:

  • Chargement: récupération et analyse du HTML en unDocument

  • Filtrage: sélectionner les données souhaitées enElements et les parcourir

  • Extraction: obtention des attributs, du texte et du code HTML des nœuds

  • Modification: ajout / modification / suppression de nœuds et modification de leurs attributs

2. Dépendance Maven

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


    org.jsoup
    jsoup
    1.10.2

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

3. Jsoup en un coup d'œil

Jsoup charge la page HTML et construit l'arborescence DOM correspondante. Cette arborescence fonctionne de la même manière que le DOM dans un navigateur, offrant des méthodes similaires à jQuery et JavaScript JavaScript pour sélectionner, parcourir, manipuler du texte / HTML / des 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("http://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 le JavaScript. Par conséquent, les modifications du DOM qui auraient normalement lieu après le chargement de la page dans un navigateur compatible avec JavaScript ne seront plus visibles dans jsoup.

4. Chargement

La phase de chargement comprend l'extraction et l'analyse du HTML en unDocument. Jsoup garantit l'analyse de tout code HTML, du plus invalide au totalement validé, comme le ferait un navigateur moderne. Cela peut être réalisé en chargeant unString, unInputStream, unFile ou une URL.

Chargeons unDocument à partir de l'URL du blog Spring:

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

Notez la méthodeget, elle représente un appel HTTP GET. Vous pouvez également faire un HTTP POST avec la méthodepost (ou vous pouvez utiliser unmethod qui reçoit le type de méthode HTTP comme paramètre).

Si vous devez détecter des codes d’état anormaux (par exemple, 404), vous devriez intercepter l'exceptionHttpStatusException:

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

Parfois, la connexion doit être un peu plus personnalisée. Jsoup.connect(…) renvoie unConnection 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("http://google.com");
connection.header("headersecurity", "xyz123");
Document docCustomConn = connection.get();

Comme 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("http://google.com")
  .header("headersecurity", "xyz123")
  .get();

Vous pouvez en savoir plus sur les paramètres deConnection parbrowsing the corresponding Javadoc.

5. Filtration

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

5.1. Sélection

La méthodeDocumentselect reçoit unString représentant le sélecteur, en utilisant la même syntaxe de sélecteuras in a CSS or JavaScript, et récupère la liste correspondante deElements. Cette liste peut être vide mais pasnull.

Jetons un œil à quelques sélections en utilisant la méthodeselect:

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 desselect génériques:

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

PuisqueElement est une superclasse deDocument, vous pouvez en savoir plus sur l'utilisation des méthodes de sélection dans les JavadocsDocument etElement.

5.2. Traversée

Traversing means navigating across the DOM tree. Jsoup fournit des méthodes qui opèrent sur lesDocument, sur un ensemble deElements, ou sur unElement spécifique, vous permettant de naviguer vers les parents, frères et sœurs ou enfants d'un nœud .

En outre, vous pouvez passer au premier, au dernier et au nième (en utilisant un index basé sur 0)Element dans un ensemble deElements:

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 ce qui est de typeElements 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. Extraire

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

Jetez un coup d'oeil à cet exemple qui sélectionne le premier article du blog et obtient sa date, son premier texte de section et enfin son code 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 lorsque vous choisissez et utilisez des sélecteurs:

  • Fiez-vous à la fonctionnalité «Afficher la source» de votre navigateur et pas seulement à la page DOM telle qu'elle a pu être modifiée (une sélection sur la console du navigateur peut produire des résultats différents de ceux de jsoup)

  • Know your selectors car il y en a beaucoup et il est toujours bon de les avoir au moins vus avant; la maîtrise des sélecteurs prend du temps

  • Use a playground for selectors pour les tester (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 id. basé)

7. Modifier

La modification englobe les attributs de configuration, le texte et le code HTML des éléments, ainsi que l’ajout et la suppression d’éléments. Cela se fait sur l'arborescence DOM précédemment générée par jsoup - lesDocument.

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

Comme dans jQuery, les méthodes de définition des attributs, du texte et du 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

Examinons 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

Pour ajouter un nouvel élément, vous devez d'abord le construire en instanciantElement. Une fois que leElement a été construit, vous pouvez l'ajouter à un autreElement en utilisant la méthodeappendChild. LesElement nouvellement créés et ajoutés seront insérés à la fin de l'élément oùappendChild est appelé:

Element link = new Element(Tag.valueOf("a"), "")
  .text("Checkout this amazing website!")
  .attr("href", "http://example.com")
  .attr("target", "_blank");
firstArticle.appendChild(link);

7.3. Supprimer des éléments

Pour supprimer des éléments, vous devez d'abord les sélectionner et exécuter la méthoderemove.

Par exemple, supprimons toutes les balises<li> qui contiennent la classe "navbar-link” deDocument, et toutes les images du premier article:

doc.select("li.navbar-link").remove();
firstArticle.select("img").remove();

7.4. Conversion du document modifié en HTML

Enfin, puisque nous modifions lesDocument, nous pourrions vouloir vérifier notre travail.

Pour ce faire, nous pouvons explorer l'arborescence DOM deDocument en sélectionnant, parcourant et extrayant à l'aide des méthodes présentées, ou nous pouvons simplement extraire son HTML en tant queString en utilisant la méthodehtml():

String docHtml = doc.html();

La sortie deString est un HTML soigné.

8. Conclusion

Jsoup est une excellente bibliothèque pour gratter n'importe quelle page. Si vous utilisez Java et que vous n'avez pas besoin de scraping basé sur un navigateur, c'est une bibliothèque à prendre en compte. Il est familier et facile à utiliser car il utilise les connaissances que vous pouvez avoir sur le développement frontal et suit les bonnes pratiques et les modèles de conception.

Vous pouvez en savoir plus sur le scraping de pages Web avec jsoup en étudiant lesjsoup API et en lisant lesjsoup cookbook.

Le code source utilisé dans ce didacticiel se trouve dans lesGitHub project.