Парсинг 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"> Также в библиотеке
Rate Limiting в Node.js: Полное руководство по защите API и управлению нагрузкой
Мониторинг приложений Rust: библиотека tracing и метрики
Mockery для PHP: полное руководство с примерами
Сериализация объектов в Node.js: JSON, Buffer и Protobuf
Работа с изображениями в Go (Golang): библиотеки и примеры