Parsing HTML en Swift (iOS/macOS) avec SwiftSoup
Lors du développement d'applications pour iOS et macOS, il est souvent nécessaire d'extraire des données de pages HTML. Que ce soit pour parser un site d'actualités, obtenir des taux de change ou analyser du contenu web — un outil fiable est indispensable. Dans le monde Swift, la bibliothèque SwiftSoup est devenue la référence de facto — un portage Swift pur du célèbre parseur Java Jsoup.
SwiftSoup fournit une API pratique pour charger, parser et manipuler des documents HTML en utilisant des sélecteurs CSS et des méthodes de parcours du DOM. La bibliothèque est entièrement écrite en Swift, ne possède aucune dépendance externe et prend en charge toutes les plateformes Apple : iOS (à partir de 11.0), macOS (10.13+), watchOS et tvOS.
Installation de SwiftSoup via Swift Package Manager
Ajoutez la dépendance dans votre fichier Package.swift ou via le menu Xcode : File → Add Packages...
// Package.swiftdependencies: [ .package(url: "https://github.com/scinfu/SwiftSoup.git", from: "2.6.0")],targets: [ .target( name: "YourTarget", dependencies: ["SwiftSoup"])]
// Ou dans Xcode : https://github.com/scinfu/SwiftSoup.git, version 2.6.0Après l'installation, importez la bibliothèque dans le fichier souhaité :
import SwiftSoupParsing de base d'une chaîne HTML
La façon la plus simple de commencer est de parser une chaîne HTML obtenue, par exemple, depuis URLSession :
let html = """<html> <body> <h1>Bonjour, le monde !</h1> <p class="content">Ceci est un texte dans un paragraphe</p> <a href="https://example.com">Lien</a> </body></html>"""
do { let doc: Document = try SwiftSoup.parse(html) let title = try doc.title() let paragraph = try doc.select("p.content").first()?.text() let link = try doc.select("a").first()?.attr("href") print("Titre : \\(title)") print("Paragraphe : \\(paragraph ?? "non trouvé")") print("Lien : \\(link ?? "non trouvé")")} catch { print("Erreur de parsing : \\(error)")}Chargement et parsing de HTML depuis le réseau
Le plus souvent, le HTML est obtenu via HTTP. Voici un exemple de chargement d'une page et d'extraction de données :
import Foundationimport SwiftSoup
func fetchAndParse(urlString: String) async { guard let url = URL(string: urlString) else { return } do { let (data, _) = try await URLSession.shared.data(from: url) guard let html = String(data: data, encoding: .utf8) else { return } let doc = try SwiftSoup.parse(html) // Extraire tous les liens let links = try doc.select("a[href]") for link in links { let href = try link.attr("href") let text = try link.text() print("\\(text) -> \\(href)") } // Extraire les titres h2 let headings = try doc.select("h2") for heading in headings { print("Titre : \\(try heading.text())") } } catch { print("Erreur : \\(error)") }}
// UtilisationTask { await fetchAndParse(urlString: "https://example.com")}Utilisation des sélecteurs CSS
SwiftSoup prend en charge pratiquement tous les sélecteurs CSS standard, ce qui rend la recherche d'éléments intuitive :
tag— par nom de balise :try doc.select("div")#id— par identifiant :try doc.select("#main-content").class— par classe :try doc.select(".article-title")[attribute]— par attribut :try doc.select("[data-id]")parent > child— descendant direct :try doc.select("ul > li")el:contains(t