Декларативный веб-скраппинг с Ferret в 2025 году

Узнайте, как Ferret упрощает декларативный веб-скраппинг в Go – от настройки до извлечения данных на статических и динамических веб-страницах.
1 мин. чтения
Ferret web scraping blog image

В этом руководстве вы узнаете:

  • Что такое Ferret и что она предлагает в качестве декларативной библиотеки для веб-скрепинга
  • Как настроить его для локального использования в среде Go
  • Как использовать его для сбора данных со статического веб-сайта
  • Как использовать его для сканирования динамического сайта
  • Основные ограничения хорька и способы их преодоления

Давайте погрузимся!

Введение в Ferret для веб-скрапинга

Прежде чем увидеть его в действии, узнайте, что такое Ferret, как он работает, что он предлагает и когда его следует использовать.

Что такое хорек?

Ferret – это библиотека веб-скреппинга с открытым исходным кодом, написанная на языке Go. Ее цель – упростить извлечение данных с веб-страниц с помощью декларативного подхода. В частности, она абстрагируется от технических сложностей парсинга и извлечения данных, используя свой собственный декларативный язык: Ferret Query Language (FQL).

Имея почти 6 тысяч звезд на GitHub, Ferret является одной из самых популярных библиотек для веб-скрепинга в Go. Она может быть встроена и поддерживает как статический, так и динамический веб-скрепинг.

FQL: Язык запросов Ferret для декларативного веб-скрапинга

Ferret Query Language (FQL) – это язык запросов общего назначения, в значительной степени вдохновленный AQL от ArangoDB. Хотя он способен на большее, FQL в основном используется для извлечения данных с веб-страниц.

FQL придерживается декларативного подхода, то есть он фокусируется на том , какие данные нужно получить, а не на том , как их получить. Как и AQL, он имеет общие черты с SQL. Но, в отличие от AQL, FQL предназначен только для чтения. Обратите внимание, что любые манипуляции с данными должны выполняться с помощью специальных встроенных функций.

Более подробную информацию о синтаксисе FQL, ключевых словах, конструкциях и поддерживаемых типах данных можно найти на странице документации по FQL.

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

Как указано на официальной странице GitHub, основные варианты использования Ferret включают:

  • Тестирование пользовательского интерфейса: Автоматизируйте тестирование веб-приложений, имитируя взаимодействие с браузером и проверяя, правильно ли ведут себя и отображаются элементы страницы в различных сценариях.
  • Машинное обучение: Извлечение структурированных данных из веб-страниц и их использование для создания высококачественных наборов данных. Затем их можно использовать для более эффективного обучения или проверки моделей машинного обучения. Узнайте, как использовать веб-скреппинг для машинного обучения.
  • Аналитика: Соскабливание и агрегирование веб-данных, таких как цены, отзывы или активность пользователей, для создания аналитических материалов, отслеживания тенденций или создания информационных панелей.

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

Начните работать с хорьком

Теперь, когда вы знаете, что такое Ferret, вы готовы увидеть его в действии на статических и динамических веб-страницах. Если вы не знаете, в чем разница между ними, прочтите наше руководство по статическому и динамическому контенту в веб-скрапинге.

Давайте настроим среду для использования Ferret для веб-скреппинга!

Пререквизиты

Убедитесь, что на вашем локальном компьютере установлено следующее:

  • Перейти на сайт
  • Docker

Чтобы убедиться, что Golang установлен и готов к работе, выполните в терминале следующую команду:

go version

Вы должны увидеть вывод, похожий на этот:

go version go1.24.3 windows/amd64

Если вы получаете ошибку, установите Golang и настройте его для вашей операционной системы.

Аналогичным образом убедитесь, что Docker установлен и правильно настроен для вашей системы.

Создайте проект “Хорёк

Теперь создайте папку для вашего проекта Ferret web scraping и перейдите в нее:

mkdir ferret-web-scraping
cd ferret-web-scraping

Скачайте Ferret CLI для вашей ОС и распакуйте прямо в папку ferret-web-scraping/. Убедитесь, что он работает, запустив:

./ferret help

На выходе должно получиться следующее:

Usage:
  ferret [flags]
  ferret [command]

Available Commands:
  browser     Manage Ferret browsers
  config      Manage Ferret configs
  exec        Execute a FQL script or launch REPL
  help        Help about any command
  update
  version     Show the CLI version information

Flags:
  -h, --help               help for ferret
  -l, --log-level string   Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")

Use "ferret [command] --help" for more information about a command.

Затем откройте папку проекта в вашей любимой IDE, например Visual Studio Code. Внутри папки проекта создайте файл с именем scraper.fql:

ferret-web-scraping/
├── ferret
├── CHANGELOG.md
├── LICENSE
├── README.md
└── scraper.fql # <-- The FQL file for web scraping in Ferret

scraper.fql будет содержать вашу декларативную логику FQL для веб-скрапинга.

Настройка докерной установки Ferret

Чтобы использовать все возможности Ferret, вы должны иметь Chrome или Chromium, установленные локально или запущенные в Docker. Официальная документация рекомендует запускать Chrome/Chromium в контейнере Docker.

Вы можете использовать любой безголовый образ на базе Chromium, но рекомендуется использовать образ montferret/chromium. Получите его с помощью:

docker pull montferret/chromium

Затем запустите этот образ Docker с помощью этой команды:

docker run -d -p 9222:9222 montferret/chromium

Примечание: Если вы хотите увидеть, что происходит в браузере во время выполнения ваших FQL-скриптов, запустите Chrome на хост-машине с включенной функцией удаленной отладки:

chrome.exe --remote-debugging-port=9222

Соскребите статический сайт с помощью Ferret

Следуйте приведенным ниже инструкциям, чтобы узнать, как использовать Ferret для соскабливания статического веб-сайта. В этом примере целевой страницей будет сайт-песочница “Books to Scrape“:

Целевой сайт "Quotes to Scrape"

Цель – извлечь ключевую информацию из каждой книги на странице, используя декларативный подход Ferret с помощью FQL.

Шаг № 1: Подключение к целевому сайту

В файле scraper.fql используйте функцию DOCUMENT для подключения к целевой странице:

LET doc = DOCUMENT("https://books.toscrape.com/")

LET позволяет определить переменную в FQL. После этой инструкции doc будет содержать HTML целевой страницы.

Шаг №2: Выберите все элементы книги

Для начала ознакомьтесь со структурой целевой веб-страницы, зайдя на нее в браузере и осмотрев ее. Для этого щелкните правой кнопкой мыши на элементе книги и выберите опцию “Inspect”, чтобы открыть DevTools:

Проверка элемента книги

Обратите внимание, что каждый элемент книги представляет собой

узел внутри родительского

. Выберите все элементы книги с помощью функции ELEMENTS():

LET book_elements = ELEMENTS(doc, "section article")

ELEMENTS() применяет к документу CSS-селектор, переданный в качестве второго аргумента. Другими словами, она выбирает нужные HTML-элементы на странице.

Итерируйте список выбранных элементов и готовьтесь применить к ним логику скраппинга:

FOR book_element IN book_elements
    // book scraping logic...

Потрясающе! Пора перебирать все элементы книги и извлекать данные из каждого.

Шаг № 3: Извлечение данных из каждой цитаты

Теперь осмотрите один элемент HTML book:

Подробный осмотр элемента HTML book

Обратите внимание, что вы можете соскоблить:

  • URL-адрес изображения из атрибута src элемента .image_container img.
  • Название книги из атрибута title элемента h3 a.
  • URL-адрес страницы книги из атрибута href узла h3 a.
  • Цена книги из текста .price_color.
  • Информация о доступности из текста в .instock.

Реализуйте эту логику разбора данных с помощью:

LET image_element = ELEMENT(book_element, ".image_container img")
LET title_element = ELEMENT(book_element, "h3 a")
LET price_element = ELEMENT(book_element, ".price_color")
LET availability_element = ELEMENT(book_element, ".instock")

RETURN {
    image_url: base_url + image_element.attributes.src,
    title: base_url+ title_element.attributes.title,
    book_url: title_element.attributes.href,
    price: TRIM(INNER_TEXT(price_element)),
    availability: TRIM(INNER_TEXT(availability_element))
}

Где base_url – переменная, определенная вне цикла for:

LET base_url = "https://books.toscrape.com/"

В приведенном выше коде:

  • ФункцияELEMENT() позволяет выбрать один элемент на странице с помощью селектора CSS.
  • attributes – это специальный атрибут, который есть у всех объектов, возвращаемых функцией ELEMENT(). Он содержит значения HTML-атрибутов текущего элемента.
  • INNER_TEXT() возвращает текст, содержащийся в текущем элементе.
  • TRIM() удаляет ведущие и завершающие пробельные символы.

Фантастика! Логика статического соскабливания завершена.

Шаг №4: Соберите все вместе

Ваш файл scraper.fql должен выглядеть следующим образом:

// connect to the target site
LET doc = DOCUMENT("https://books.toscrape.com/")

// select the book HTML elements
LET book_elements = ELEMENTS(doc, "section article")

// the base URL of the target site
LET base_url = "https://books.toscrape.com/"

// iterate over each book element and apply the scraping logic
FOR book_element IN book_elements
    // select all info elements
    LET image_element = ELEMENT(book_element, ".image_container img")
    LET title_element = ELEMENT(book_element, "h3 a")
    LET price_element = ELEMENT(book_element, ".price_color")
    LET availability_element = ELEMENT(book_element, ".instock")

    // scrape the data of interest
    RETURN {
        image_url: base_url + image_element.attributes.src,
        title: base_url+ title_element.attributes.title,
        book_url: title_element.attributes.href,
        price: TRIM(INNER_TEXT(price_element)),
        availability: TRIM(INNER_TEXT(availability_element))
    }

Как видите, логика скраппинга больше сосредоточена на том, какие данные извлекать, а не на том, как их извлекать. В этом и заключается сила декларативного веб-скреппинга с Ferret!

Шаг #5: Выполните сценарий FQL

Выполните свой сценарий Ferret с помощью:

./ferret exec scraper.fql

В терминале вывод будет таким:

[{"availability":"In stock","book_url":"catalogue/a-light-in-the-attic_1000/index.html","image_url":"https://books.toscrape.com/media/cache/2c/da/2cdad67c44b002e7ead0cc35693c0e8b.jpg","price":"£51.77","title":"https://books.toscrape.com/A Light in the Attic"},{"availability":"In stock","book_url":"catalogue/tipping-the-velvet_999/index.html","image_url":"https://books.toscrape.com/media/cache/26/0c/260c6ae16bce31c8f8c95daddd9f4a1c.jpg","price":"£53.74","title":"https://books.toscrape.com/Tipping the Velvet"},
// omitted for brevity...
,{"availability":"In stock","book_url":"catalogue/its-only-the-himalayas_981/index.html","image_url":"https://books.toscrape.com/media/cache/27/a5/27a53d0bb95bdd88288eaf66c9230d7e.jpg","price":"£45.17","title":"https://books.toscrape.com/It's Only the Himalayas"}]

Это строка JSON, содержащая все данные о книгах, собранные с веб-страницы, как и предполагалось. Для ознакомления с недекларативным подходом к разбору данных посмотрите наше руководство по веб-скраппингу с помощью Go.

Миссия выполнена!

Соскоб динамического сайта с помощью Ferret

Ferret также поддерживает соскабливание динамических сайтов, требующих выполнения JavaScript. В этом разделе руководства целевым сайтом будет версия сайта “Quotes to Scrape” с задержкой выполнения JavaScript:

Обратите внимание, как элементы цитат добавляются на страницу с задержкой

Страница использует JavaScript для динамического введения элементов цитат в DOM после небольшой задержки. Этот сценарий требует выполнения JavaScript – отсюда и необходимость рендеринга страницы в браузере. (Именно поэтому мы ранее установили контейнер Chromium Docker).

Выполните следующие шаги, чтобы узнать, как работать с динамическими веб-страницами с помощью Ferret!

Шаг № 1: Подключитесь к целевой странице в браузере

Используйте следующие строки для подключения к целевой странице через безголовый браузер:

LET doc = DOCUMENT("https://quotes.toscrape.com/js-delayed/?delay=2000", {
    driver: "cdp"
})

Обратите внимание на использование поля driver в функции DOCUMENT(). Это то, что указывает Ferret на рендеринг страницы в безголовом экземпляре Chroumium, настроенном через Docker.

Шаг №2: Подождите, пока целевые элементы появятся на странице

Зайдите на целевую страницу в браузере, дождитесь загрузки элементов цитаты и осмотрите один из них:

Проверка элемента цитаты

Обратите внимание, что элементы цитат можно выбрать с помощью CSS-селектора .quote. Эти элементы цитат будут отображаться с помощью JavaScript с небольшой задержкой, поэтому их нужно дождаться.

Используйте функцию WAIT_ELEMENT() в Ferret, чтобы дождаться появления на странице элементов цитаты:

// wait up to 5 seconds for the quote elements to be on the page
WAIT_ELEMENT(doc, ".quote", 5000)

Это очень важная конструкция, которую необходимо использовать при соскабливании динамических веб-страниц, которые используют JavaScript для отображения контента.

Шаг № 3: Примените логику скрапинга

Теперь сосредоточьтесь на HTML-структуре информационных элементов внутри узла .quote:

Детальный осмотр элемента .quote

Обратите внимание, что вы можете соскоблить:

  • Текст цитаты из .quote
  • Автор из .author

Реализуйте логику веб-скрептинга Ferret с помощью:

// select the quote HTML elements
LET quote_elements = ELEMENTS(doc, ".quote")

// iterate over each quote element and apply the scraping logic
FOR quote_element IN quote_elements
    // select all info elements
    LET text_element = ELEMENT(quote_element, ".text")
    LET author_element = ELEMENT(quote_element, ".author")

    // scrape the data of interest
    RETURN {
        quote: TRIM(INNER_TEXT(text_element)),
        author: TRIM(INNER_TEXT(author_element))
    } 

Потрясающе! Логика парсинга завершена.

Шаг № 4: Соберите все

Файл scraper.fql должен содержать:

// connect to the target site via the Chromium headless instance
LET doc = DOCUMENT("https://quotes.toscrape.com/js-delayed/?delay=2000", {
    driver: "cdp"
})

// wait up to 5 seconds for the quote elements to be on the page
WAIT_ELEMENT(doc, ".quote", 5000)

// select the quote HTML elements
LET quote_elements = ELEMENTS(doc, ".quote")

// iterate over each quote element and apply the scraping logic
FOR quote_element IN quote_elements
    // select all info elements
    LET text_element = ELEMENT(quote_element, ".text")
    LET author_element = ELEMENT(quote_element, ".author")

    // scrape the data of interest
    RETURN {
        quote: TRIM(INNER_TEXT(text_element)),
        author: TRIM(INNER_TEXT(author_element))
    }

Как видите, это не сильно отличается от сценария для статического сайта. Причина опять же в том, что Ferret использует декларативный подход к веб-скреппингу.

Шаг #5: Выполните код FQL

Запустите свой скрипт для скрапбукинга Ferret с помощью:

./ferret exec scraper.fql

На этот раз результат будет таким:

[{"author":"Albert Einstein","quote":"“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”"},{"author":"J.K. Rowling","quote":"“It is our choices, Harry, that show what we truly are, far more than our abilities.”"},{"author":"Albert Einstein","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":"Jane Austen","quote":"“The person, be it gentleman or lady, who has not pleasure in a good novel, must be intolerably stupid.”"},{"author":"Marilyn Monroe","quote":"“Imperfection is beauty, madness is genius and it's better to be absolutely ridiculous than absolutely boring.”"},{"author":"Albert Einstein","quote":"“Try not to become a man of success. Rather become a man of value.”"},{"author":"André Gide","quote":"“It is better to be hated for what you are than to be loved for what you are not.”"},{"author":"Thomas A. Edison","quote":"“I have not failed. I've just found 10,000 ways that won't work.”"},{"author":"Eleanor Roosevelt","quote":"“A woman is like a tea bag; you never know how strong it is until it's in hot water.”"},{"author":"Steve Martin","quote":"“A day without sunshine is like, you know, night.”"}]

И вуаля! Это именно то структурированное содержимое, которое извлекается из страницы, преобразованной с помощью JavaScript.

Ограничения декларативного подхода к веб-скрапингу Ferret

Ferret, несомненно, является мощным инструментом и одним из немногих, использующих декларативный подход к веб-скраппингу. Тем не менее, у него есть как минимум три существенных недостатка:

  • Плохая документация и нечастые обновления: Хотя официальная документация содержит полезные тексты, в ней отсутствуют полные ссылки на API. Это затрудняет создание сложных скриптов. Кроме того, проект не получает регулярных обновлений, а это значит, что он может отставать от современных технологий скрапинга.
  • Нет поддержки обхода защиты от скраппинга: Ferret не предлагает встроенных механизмов для работы с CAPTCHA, ограничениями скорости или другими продвинутыми средствами защиты от скрапинга. Это делает его непригодным для обхода более защищенных сайтов.
  • Ограниченная выразительность: FQ, язык запросов Ferret Query Language, все еще находится в стадии разработки и не предлагает такого уровня гибкости и контроля, как более современные инструменты для скраппинга, такие как Playwright или Puppeteer.

Эти ограничения не могут быть легко устранены с помощью простых интеграций. Кроме того, не стоит забывать, что основной задачей Ferret является получение веб-данных. Таким образом, решение состоит в том, чтобы рассмотреть более надежную альтернативу.

Инфраструктура искусственного интеллекта Bright Data включает в себя набор передовых услуг, предназначенных для надежного и интеллектуального извлечения веб-данных. Они позволяют извлекать данные с любого веб-сайта и в больших масштабах.

Заключение

В этом уроке вы узнали, как использовать Ferret для декларативного веб-скреппинга в Go. Как было продемонстрировано, эта библиотека позволяет извлекать данные как со статических, так и с динамических страниц, фокусируясь на том, что извлекать, а не на том, как извлекать.

Проблема в том, что Ferret имеет ряд ограничений, поэтому он может оказаться не самым лучшим решением. Если вы ищете более рациональный и масштабируемый способ получения веб-данных, рассмотрите возможность использования Web Scraper APIs – специальныхконечных точек для извлечения свежих, структурированных и полностью соответствующих требованиям веб-данных с более чем 120 популярных веб-сайтов.

Зарегистрируйте бесплатную учетную запись Bright Data сегодня и испытайте нашу мощную инфраструктуру веб-скреппинга!