Парсинг HTML в Swift (iOS/macOS): библиотеки SwiftSoup и Fuzi

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Парсинг HTML в Swift (iOS/macOS): обзор библиотек SwiftSoup и Fuzi

При разработке приложений для iOS и macOS часто возникает необходимость извлечения данных из веб-страниц. Парсинг HTML позволяет автоматически получать контент, структурировать его и использовать в приложении. В экосистеме Swift для этих целей существует несколько мощных библиотек. В этой статье мы подробно рассмотрим две самые популярные: SwiftSoup и Fuzi. Вы узнаете, как установить их, как выполнять базовые операции парсинга и какие особенности у каждой из них.

Зачем нужен парсинг HTML в Swift?

Парсинг HTML пригодится в следующих сценариях:

  • Агрегация данных — сбор новостей, цен, описаний товаров с нескольких сайтов.
  • Мониторинг изменений — отслеживание обновлений на целевых страницах.
  • Интеграция с веб-сервисами — если сайт не предоставляет API, парсинг — единственный способ получить данные.
  • Автоматизация тестирования — проверка корректности HTML-структуры.

Библиотека SwiftSoup

SwiftSoup — это Swift-порт популярной Java-библиотеки Jsoup. Она предоставляет удобный API для парсинга, навигации и манипуляции HTML-документами. SwiftSoup поддерживает CSS-селекторы, что делает извлечение элементов простым и интуитивным.

Установка SwiftSoup

Добавьте зависимость в ваш Package.swift или через Swift Package Manager в Xcode:

// Package.swift
dependencies: [
    .package(url: "https://github.com/scinfu/SwiftSoup.git", from: "2.6.0")
]

Пример использования SwiftSoup

Рассмотрим простой пример: загрузим HTML-строку и извлечём заголовки <h2> и ссылки <a>.

import SwiftSoup

func parseHTML() {
    let html = """
    <html>
        <body>
            <h2>Заголовок статьи</h2>
            <p>Текст абзаца.</p>
            <a href="https://example.com">Ссылка</a>
        </body>
    </html>
    """
    
    do {
        let doc = try SwiftSoup.parse(html)
        
        // Извлекаем все заголовки h2
        let headers = try doc.select("h2")
        for header in headers {
            print("Заголовок: \(try header.text())")
        }
        
        // Извлекаем все ссылки
        let links = try doc.select("a[href]")
        for link in links {
            let linkText = try link.text()
            let linkHref = try link.attr("href")
            print("Текст: \(linkText), URL: \(linkHref)")
        }
        
    } catch {
        print("Ошибка парсинга: \(error)")
    }
}

В этом примере мы используем метод select() с CSS-селектором "h2" для выбора всех заголовков второго уровня, и "a[href]" — для выбора всех ссылок с атрибутом href. Метод text() возвращает текстовое содержимое элемента, а attr() — значение указанного атрибута.

Навигация по дереву документа

SwiftSoup позволяет перемещаться по DOM-дереву:

// Получить первый элемент h2
if let firstHeader = try doc.select("h2").first() {
    print("Первый заголовок: \(try firstHeader.text())")
}

// Получить родительский элемент
let parent = try firstHeader.parent()
print("Родитель: \(try parent?.tagName() ?? "nil")")

// Получить следующий соседний элемент
let nextSibling = try firstHeader.nextElementSibling()
print("Следующий элемент: \(try nextSibling?.tagName() ?? "nil")")

Библиотека Fuzi

Fuzi — ещё одна популярная библиотека для парсинга HTML и XML в Swift. Она основана на libxml2 и отличается высокой производительностью. Fuzi также поддерживает CSS-селекторы и XPath-запросы.

Установка Fuzi

Добавьте зависимость в Package.swift:

dependencies: [
    .package(url: "https://github.com/cezheng/Fuzi.git", from: "3.1.0")
]

Пример использования Fuzi

import Fuzi

func parseWithFuzi() {
    let html = """
    <html>
        <body>
            <div class="content">                    

Рекомендаций