В этом руководстве вы узнаете:
- Что такое 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“:
Цель – извлечь ключевую информацию из каждой книги на странице, используя декларативный подход 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:
Обратите внимание, что вы можете соскоблить:
- 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
- Автор из
.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 сегодня и испытайте нашу мощную инфраструктуру веб-скреппинга!