Python и JavaScript доминируют во всей индустрии скрапбукинга. Если вам нужна производительность или переносимость, Scala предлагает сильную альтернативу. Scala дает нам компилируемую, переносимую и сильно типизированную основу для работы.
Сегодня мы рассмотрим, как скреативить с помощью Scala и jsoup. Хотя о нем пишут не так часто, как о веб-скрапинге на Python, Scala обеспечивает прочный фундамент и достойные инструменты для скрапинга.
Почему именно Scala?
Существует довольно много причин, по которым вы можете выбрать Scala вместо Python или JavaScript.
- Производительность: Scala компилируется в JVM (Java Virtual Machine). Компиляторы переводят наш код в исполняемый на машине байткод. Это делает его изначально более быстрым, чем Python.
 - Статическая типизация: Проверка типов обеспечивает дополнительный уровень безопасности. Многие распространенные ошибки отлавливаются еще до запуска программы.
 - Переносимость: Scala компилируется в байткод JVM (Java Virtual Machine). Байткод JVM может выполняться везде, где установлена Java.
 - Полная совместимость с Java: Вы можете использовать зависимости Java в коде Scala. Это значительно расширяет доступную вам экосистему.
 
Начало работы
Прежде чем приступить к работе, необходимо убедиться, что у вас установлена Scala. Ниже мы приводим инструкции для Ubuntu, macOS и Windows.
Полную документацию по установке можно посмотреть здесь.
Ubuntu
curl -fL https://github.com/coursier/coursier/releases/latest/download/cs-x86_64-pc-linux.gz | gzip -d > cs && chmod +x cs && ./cs setup
macOS
brew install coursier && coursier setup
Windows
Загрузите программу установки Scala для Windows.
Создание скребка
Создайте новую папку проекта и перейдите в нее по cd.
mkdir quote-scraper
cd quote-scraper
Инициализируйте новый проект Scala. Эта команда преобразует нашу новую папку в проект Scala и создает файл build.sbt для хранения наших зависимостей.
sbt new scala/scala3.g8
Теперь откройте файл build.sbt. Вам нужно будет добавить jsoup в качестве зависимости. Ваш полный файл сборки должен выглядеть следующим образом.
val scala3Version = "3.6.3"
lazy val root = project
  .in(file("."))
  .settings(
    name := "quote-scraper",
    version := "0.1.0-SNAPSHOT",
    scalaVersion := scala3Version,
    libraryDependencies += "org.scalameta" %% "munit" % "1.0.0" % Test,
    libraryDependencies += "org.jsoup" % "jsoup" % "1.18.3"
  )
Затем скопируйте и вставьте приведенный ниже код в файл Main.scala.
import org.jsoup.Jsoup
import scala.jdk.CollectionConverters._
@main def QuotesScraper(): Unit =
  val url = "http://quotes.toscrape.com"
  try
    val document = Jsoup.connect(url).get()
    //find all objects on the page with the quote class
    val quotes = document.select(".quote")
    for quote <- quotes.asScala do
      //find the first object with the class "text" and return its text
      val text = quote.select(".text").text()
      //find the first object with the class "author" and return its text
      val author = quote.select(".author").text()
      println(s"Quote: $text")
      println(s"Author: $author")
      println("-" * 50)
  
  catch case e: Exception => println(s"Error: ${e.getMessage}")
Запуск скребка
Чтобы запустить наш скребок, выполните следующую команду из корня проекта.
sbt run
Вы должны увидеть результат, аналогичный приведенному ниже.
Quote: “The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”
Author: Albert Einstein
--------------------------------------------------
Quote: “It is our choices, Harry, that show what we truly are, far more than our abilities.”
Author: J.K. Rowling
--------------------------------------------------
Quote: “There are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle.”
Author: Albert Einstein
--------------------------------------------------
Quote: “The person, be it gentleman or lady, who has not pleasure in a good novel, must be intolerably stupid.”
Author: Jane Austen
--------------------------------------------------
Quote: “Imperfection is beauty, madness is genius and it's better to be absolutely ridiculous than absolutely boring.”
Author: Marilyn Monroe
--------------------------------------------------
Quote: “Try not to become a man of success. Rather become a man of value.”
Author: Albert Einstein
--------------------------------------------------
Quote: “It is better to be hated for what you are than to be loved for what you are not.”
Author: André Gide
--------------------------------------------------
Quote: “I have not failed. I've just found 10,000 ways that won't work.”
Author: Thomas A. Edison
--------------------------------------------------
Quote: “A woman is like a tea bag; you never know how strong it is until it's in hot water.”
Author: Eleanor Roosevelt
--------------------------------------------------
Quote: “A day without sunshine is like, you know, night.”
Author: Steve Martin
--------------------------------------------------
[success] Total time: 6 s, completed Feb 18, 2025, 8:58:04 PM
Выбор с помощью jsoup
Чтобы найти элементы страницы с помощью jsoup, мы используем метод select(). select() возвращает список всех элементов, соответствующих нашему селектору. Давайте посмотрим, как это работает в нашем проекте Quote Scraper.
В этой строке мы используем document.select(".quote"), чтобы вернуть все элементы страницы с классом quote.
val quotes = document.select(".quote")
Мы также можем написать эти селекторы с большей структурой: element[attribute='some value']. Это позволит нам применять более сильные фильтры при поиске объектов на странице.
Строка ниже все равно вернет те же объекты страницы, но она гораздо выразительнее.
val quotes = document.select("div[class='quote']")
Давайте рассмотрим еще несколько примеров использования select() в нашем коде. Поскольку в каждой цитате есть только один текстовый элемент и один автор, select() возвращает только один текстовый объект и одного автора. Если бы наш элемент цитаты содержал несколько текстов или авторов, то select() вернул бы все тексты и авторов для каждой цитаты.
//find objects with the class "text" and return their text
val text = quote.select(".text").text()
//find objects with the class "author" and return their text
val author = quote.select(".author").text()
Извлечение с помощью jsoup
Для извлечения данных с помощью jsoup мы можем использовать следующие методы:
text(): Извлечение текста из списка элементов страницы. Когда вы извлекаете цены с веб-сайта, они отображаются на странице в виде текста.attr(): Извлечение определенного атрибута из одного элемента страницы. Это части данных, расположенные внутри HTML-тегов. Этот метод обычно используется для извлечения ссылок с веб-сайта.
text()
Мы видели примеры этого на примере нашего начального скрепера. text() возвращает текст всех элементов, к которым мы обращаемся. Если в приведенном ниже примере нужно найти двух авторов, text() извлечет оба их текста и объединит их в одну строку.
//find objects with the class "text" and return their text
val text = quote.select(".text").text()
//find objects with the class "author" and return their text
val author = quote.select(".author").text()
attr()
Метод attr() ведет себя иначе, чем text(). Этот метод извлекает один атрибут из одного элемента страницы.
//find link elements with the class "tag" and extract the "href" from the first one
val firstTagLink = quote.select("a[class='tag']").attr("href")
После добавления этой строки наш вывод выглядит следующим образом.
Quote: “The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”
Author: Albert Einstein
First Tag Link: /tag/change/page/1/
--------------------------------------------------
Quote: “It is our choices, Harry, that show what we truly are, far more than our abilities.”
Author: J.K. Rowling
First Tag Link: /tag/abilities/page/1/
--------------------------------------------------
Quote: “There are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle.”
Author: Albert Einstein
First Tag Link: /tag/inspirational/page/1/
--------------------------------------------------
Quote: “The person, be it gentleman or lady, who has not pleasure in a good novel, must be intolerably stupid.”
Author: Jane Austen
First Tag Link: /tag/aliteracy/page/1/
--------------------------------------------------
Quote: “Imperfection is beauty, madness is genius and it's better to be absolutely ridiculous than absolutely boring.”
Author: Marilyn Monroe
First Tag Link: /tag/be-yourself/page/1/
--------------------------------------------------
Quote: “Try not to become a man of success. Rather become a man of value.”
Author: Albert Einstein
First Tag Link: /tag/adulthood/page/1/
--------------------------------------------------
Quote: “It is better to be hated for what you are than to be loved for what you are not.”
Author: André Gide
First Tag Link: /tag/life/page/1/
--------------------------------------------------
Quote: “I have not failed. I've just found 10,000 ways that won't work.”
Author: Thomas A. Edison
First Tag Link: /tag/edison/page/1/
--------------------------------------------------
Quote: “A woman is like a tea bag; you never know how strong it is until it's in hot water.”
Author: Eleanor Roosevelt
First Tag Link: /tag/misattributed-eleanor-roosevelt/page/1/
--------------------------------------------------
Quote: “A day without sunshine is like, you know, night.”
Author: Steve Martin
First Tag Link: /tag/humor/page/1/
--------------------------------------------------
[success] Total time: 3 s, completed Feb 18, 2025, 10:29:30 PM
Альтернативные инструменты для веб-скрепинга
- Браузер для скрапинга: Удаленный браузер, полностью интегрированный с прокси, который можно использовать из Playwright и Selenium.
 - API-интерфейсы для веб-скраперов: Автоматизируйте процесс скрапинга, вызвав один из наших API. Когда вы вызываете API-скребок, мы скребем сайт и отправляем данные обратно вам.
 - Скребок без кода: Сообщите нам, какой сайт вы хотите скрапировать и какие данные вам нужны. Остальное мы сделаем сами.
 - Наборы данных: Наши базы данных, пожалуй, самые простые из всех методов извлечения информации. Мы сканируем сотни сайтов и постоянно обновляем наши базы данных. Наборы данных дают вам чистый набор данных, готовый к анализу.
 
Заключение
Веб-скраппинг довольно интуитивно понятен в Scala. Вы узнали, как выбирать элементы страницы и извлекать из них данные с помощью jsoup. Если скраппинг – не ваш конек, вы всегда можете воспользоваться одним из наших автоматизированных инструментов, чтобы направить процесс в нужное русло, или полностью отказаться от него, используя наши готовые наборы данных.
Зарегистрируйтесь и начните бесплатную пробную версию уже сегодня!