Парсинг и скрапинг данных на Kotlin: от новичка до реального проекта

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

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

Начать курс

Парсинг и скрапинг данных на Kotlin: почему это стоит вашего внимания

Когда речь заходит о сборе данных из интернета, в голову чаще всего приходит Python с его BeautifulSoup и Scrapy. Но что, если ваш стек — это JVM, а душа лежит к лаконичному и безопасному коду? Знакомьтесь: Kotlin. Этот язык не просто «ещё один Java», а мощный инструмент для парсинга и скрапинга данных, который позволяет писать чистый, производительный и асинхронный код без лишнего шума.

В этой статье мы разберём, как превратить Kotlin в настоящий комбайн для сбора информации. Вы узнаете, какие библиотеки использовать, как не попасть под бан сайта и как обрабатывать тысячи страниц без головной боли. Поехали!

Что такое парсинг и скрапинг данных на Kotlin

Прежде чем нырять в код, давайте расставим точки над i.

  • Веб-скрапинг (scraping) — это массовое извлечение данных с веб-страниц. Вы загружаете HTML, разбираете его и забираете нужные кусочки: цены, заголовки, описания товаров.
  • Парсинг (parsing) — более узкое понятие. Это разбор структуры данных (HTML, JSON, XML) в удобный для программы вид. Парсинг — часть скрапинга.

В Kotlin парсинг и скрапинг данных реализуются элегантно благодаря функциональным возможностям, строгой типизации и превосходной поддержке корутин. Вы получаете код, который легко читать, тестировать и поддерживать.

Библиотеки для парсинга и скрапинга данных на Kotlin

Выбор библиотеки — 50% успеха. Вот основной джентльменский набор для Kotlin:

  • Jsoup — золотой стандарт парсинга HTML. Работает на JVM, понимает даже кривую вёрстку.
  • Ktor Client — асинхронный HTTP-клиент от JetBrains. Идеально для связки с корутинами.
  • kotlinx.serialization — сериализация JSON без боли.
  • OkHttp — если нужен более низкоуровневый контроль над запросами.
  • HtmlUnit — для сайтов, которые рендерят контент через JavaScript (редко, но бывает).

В этой статье мы сфокусируемся на связке Ktor + Jsoup + kotlinx.serialization — это даёт максимум контроля и скорости.

Практический пример: парсинг данных с сайта на Kotlin

Лучший способ понять скрапинг данных на Kotlin — написать реальный скрипт. Представим, что мы собираем информацию о книгах с сайта-агрегатора (например, с хабра или книжного магазина). Наша цель: получить название, автора и цену каждой книги.

Шаг 1. Настройка проекта

Создайте новый Gradle-проект и добавьте зависимости в build.gradle.kts:

dependencies {
    implementation("io.ktor:ktor-client-core:2.3.7")
    implementation("io.ktor:ktor-client-cio:2.3.7")
    implementation("org.jsoup:jsoup:1.17.2")
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2")
    implementation("ch.qos.logback:logback-classic:1.4.14")
}

Шаг 2. Пишем HTTP-клиент для загрузки страниц

Используем Ktor Client для асинхронной загрузки. Корутины позволяют делать это без блокировки потока.

import io.ktor.client.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import kotlinx.coroutines.runBlocking

class PageLoader(private val client: HttpClient) {

    suspend fun loadPage(url: String): String {
        val response: HttpResponse = client.get(url)
        return response.bodyAsText()
    }
}

fun main() = runBlocking {
    val client = HttpClient {
        // можно настроить таймауты, юзер-агенты и т.д.
    }
    val loader = PageLoader(client)
    val html = loader.loadPage("https://example-books.com/catalog")
    println(html.take(500)) // выведем первые 500 символов для проверки
    client.close()
}

Шаг 3. Парсим HTML с помощью Jsoup

Теперь самое интересное — извлекаем данные. Допустим, каждая книга лежит в блоке <div class="book-item">.

import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.select.Elements

data class Book(
    val title: String,
    val author: String,
    val price: Double
)

fun parseBooks(html: String): List<Book> {
    val doc: Document = Jsoup.parse(html)
    val items: Elements = doc.select("div.book-item")

    return items.map { item ->
        val title = item.select("h2.book-title").text()
        val author = item.select("p.author").text()
        val priceText = item.select("span.price").text()
            .replace("₽", "").trim()
        val price = priceText.toDoubleOrNull() ?: 0.0

        Book(title, author, price)
    }
}

Обратите внимание: Jsoup понимает CSS-селекторы, так что вы можете гибко настраивать извлечение. Это основа любого парсинга HTML на Kotlin.

Шаг 4. Собираем всё вместе и сохраняем результат

Добавим сохранение в JSON с помощью kotlinx.serialization.

import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json

@Serializable
data class BookDto(
    val title: String,
    val author: String,
    val price: Double
)

fun List<Book>.toDtoList(): List<BookDto> = this.map {
    BookDto(it.title, it.author, it.price)
}

fun saveToJson(books: List<BookDto>, filename: String) {
    val json = Json { prettyPrint = true }
    val jsonString = json.encodeToString(books)
    java.io.File(filename).writeText(jsonString)
}

// В main:
fun main() = runBlocking {
    val client = HttpClient()
    val loader = PageLoader(client)

    val html = loader.loadPage("https://example-books.com/catalog")
    val books = parseBooks(html)
    val dtos = books.toDtoList()

    saveToJson(dtos, "books.json")
    println("Сохранено ${books.size} книг")
    client.close()
}

Вот так, меньше чем за 50 строк кода, мы реализовали полноценный скрапинг данных на Kotlin. Но это только начало!

Продвинутые техники: пагинация, многопоточность и обход блокировок

Пагинация: собираем все страницы

Редкий сайт показывает все данные на одной странице. Обычно есть пагинация. Давайте научимся её обрабатывать.

suspend fun scrapeAllPages(baseUrl: String, loader: PageLoader                

Блоги

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