Практическое руководство по веб-скрапингу в R

В этом руководстве мы рассмотрим все шаги, связанные с веб-скрапингом в R с помощью rvest с целью извлечения отзывов о товарах из одного общедоступного URL с сайта Amazon.
2 min read
Web scraping with R - featured image

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

Начало работы с веб-скрапингом в R

Первым шагом станет обзор инструментов, которые мы будем использовать в этом учебнике по R.

Понимание инструментов: R и rvest

R — богатая и простая в использовании библиотека для статистического анализа и визуализации данных, которая предоставляет полезные инструменты для работы с данными и динамической типизацией.  

rvest 一 от «harvest»一 один из самых популярных пакетов R, предоставляющий функции веб-скрапинга, в том числе и благодаря чрезвычайно удобному интерфейсу. Ванильный rvest позволяет извлекать данные только с одной веб-страницы, что идеально подходит для первоначального исследования. Впоследствии вы можете расширить его с помощью библиотеки polite для скрапинга большего количества веб-страниц.  

Настройка среды разработки

Если вы еще не используете R в RStudio, следуйте приведенным здесь инструкциям по его установке.  

После этого откройте консоль и установите rvest:

install.packages("rvest")

Официальная рекомендация заключается в расширении встроенных функций rvest за счет дополнительных пакетов из коллекции tidyverse — например, magrittr, который улучшает читабельность кода, или xml2, позволяющего работать с HTML и XML. Вы можете сделать это, установив tidyverse:

install.packages("tidyverse")

Понимание веб-страницы

Веб-скрапинг — это технология получения данных с веб-сайтов в рамках соответствующих автоматизированных процессов.

Из этого определения вытекают три важных момента:

  • Данные поступают в различных форматах.
  • Сайты отображают информацию совершенно разными способами.
  • Получаемые с помощью веб-скрапинга данные должны находиться в открытом доступе.

Чтобы понять, как выполнить веб-скрапинг целевого URL, сначала необходимо разобраться, как отображается содержимое веб-страницы с помощью языка разметки HTML и CSS.

HTML отвечает за содержание и структуру веб-страницы 一 язык разметки загружается в веб-браузер для создания древовидной объектной модели документа (DOM) 一 путем организации ее содержимого с помощью специальных тегов, которые имеют иерархическую структуру. Каждый из них обладает определенной функциональностью, применяемой ко всему содержимому, находящему внутри его открывающих (<>) и закрывающих угловых скобок (</>):  

<!DOCTYPE html>
<html lang="en-gb" class="a-ws a-js a-audio a-video a-canvas a-svg a-drag-drop a-geolocation a-history a-webworker a-autofocus a-input-placeholder a-textarea-placeholder a-local-storage a-gradients a-transform3d -scrolling a-text-shadow a-text-stroke a-box-shadow a-border-radius a-border-image a-opacity a-transform a-transition a-ember" data-19ax5a9jf="dingo" data-aui-build-date="3.22.2-2022-12-01">
▶<head>..</head>
▶<body class="a-aui_72554-c a-aui_accordion_a11y_role_354025-c a-aui_killswitch_csa_logger_372963-c a-aui_launch_2021_ally_fixes_392482-t1 a-aui_pci_risk_banner_210084-c a-aui_preload_261698-c a-aui_rel_noreferrer_noopener_309527-c a-aui_template_weblab_cache_333406-c a-aui_tnr_v2_180836-c a-meter-animate" style="padding-bottom: 0px;">..</body>
</html>

Тег <html> является обязательным элементом любой веб-страницы, внутри которого вложены еще два — <head> и <body>. Последние также являются родительскими для множества других тегов, среди которых самые популярные — это <div> (для секции документа) и <p> (для параграфа).  

В приведенном выше фрагменте вы можете увидеть атрибуты, связанные с каждым HTML-элементом: lang, class и style создаются по умолчанию, тогда как атрибуты, которые начинаются с «data-» — являются на Amazon пользовательскими.  

класс и атрибут id представляют особый интерес для веб-скрапинга, поскольку позволяют точно нацелиться на один или несколько элементов. Изначально они были внедрены для упрощения стилизации веб-страницы с помощью CSS.  

CSS отвечает за внешнюю стилизацию веб-страницы. С его помощью можно выбрать конкретный элемент HTML и изменить его цвет, размер, позиционирование и любое другое свойство. Вы можете применить CSS-стиль непосредственно внутри целевого HTML-элемента, используя для этого специальный атрибут style, как показано в приведенном выше фрагменте:  

<body .. style="padding-bottom: 0px;">

На чистом CSS это будет выглядеть следующим образом:

body {padding-bottom: 0px;}

Здесь body — это выбранный селектор, padding-bottom — свойство, а 0px — его значение. Любой тег, класс или id может быть использован в качестве селектора CSS.  

Интернет-пользователи могут динамически взаимодействовать с содержимым веб-страницы с помощью функций JavaScript благодаря внедрению в HTML-разметку специального тега script. После взаимодействия с пользователем отображаемое содержимое может измениться, а вместо него появится новое; продвинутые веб-скраперы могут имитировать действия реальных пользователей, о чем мы поговорим позже.  

Понимание DevTools

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

Инструменты разработчика можно найти в настройках, которые открываются при нажатии на три вертикальные точки в верхнем правом углу браузера, в разделе «Дополнительные инструменты»:

Процесс открытия инструментов разработчика в Chrome
Процесс открытия инструментов разработчика в Chrome

С помощью инструментов разработчика вы сможете увидеть во вкладке «Элементы» HTML-код веб-страницы. При наведении на любую из строк HTML-кода соответствующий ей элемент на веб-странице выделяется синим цветом:

Процесс доступа к отрисованным элементам веб-страницы из инструментов разработчика в Chrome
Процесс доступа к отрисованным элементам веб-страницы из инструментов разработчика в Chrome

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

Эти два процесса — все, что нужно, чтобы извлечь дескрипторы CSS для нашего практического руководства.

Глубокое погружение в веб-скрапинг в R: Учебник

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

Предустановки

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

  • R = 4.2.2
  • rvest = 1.0.3
  • tidyverse = 1.3.2

Интерактивное изучение веб-страницы

Вы можете использовать DevTools в Chrome для изучения HTML вашего URL и создания списка всех классов и идентификаторов HTML-элементов, которые содержат интересующую вас информацию, т.е. обзоры продуктов:

Отзыв покупателя со страницы товара Amazon, выбранный с помощью DevTools в Chrome
Отзыв покупателя со страницы товара Amazon, выбранный с помощью DevTools в Chrome

Каждый отзыв клиента располагается в div с id в следующем формате:  

customer_review_$INTERNAL_ID.

Содержимое HTML-элемента div, соответствующее отзыву покупателя на скриншоте выше, выглядит следующим образом:

<div id="customer_review-R2U9LWUSIPY0GS" class="a-section celwidget" data-csa-c-id="kj23dv-axnw47-69iej3-apdvzi" data-cel-widget="customer_review-R2U9LWUSIPY0GS">
<div data-hook="genome-widget" class="a-row a-spacing-mini">..</div>
<div class="a-row">
<a class="a-link-normal" title="4.0 out of 5 stars" href="https://www.amazon.co.uk/gp/customer-reviews/R2U9LWUSIPY0GS/ref=cm_cr_dp_d_rvw_ttl?ie=UTF8&amp;ASIN=B07SR4R8K1">
<i data-hook="review-star-rating" class="a-icon a-icon-star a-star-4 review-rating">
<span class="a-icon-alt">4.0 out of 5 stars</span>
</i>
</a>
<span class="a-letter-space"></span>
<a data-hook="review-title" class="a-size-base a-link-normal review-title a-color-base review-title-content a-text-bold" href="https://www.amazon.co.uk/gp/customer-reviews/R2U9LWUSIPY0GS/ref=cm_cr_dp_d_rvw_ttl?ie=UTF8&amp;ASIN=B07SR4R8K1">
 		<span>Very good controller if a little overpriced</span>
  	 </a>
</div>
<span data-hook="review-date" class="a-size-base a-color-secondary review-date">..</span>
<div class="a-row a-spacing-mini review-data review-format-strip">..</div>
<div class="a-row a-spacing-small review-data">
<span data-hook="review-body" class="a-size-base review-text">
<div data-a-expander-name="review_text_read_more" data-a-expander-collapsed-height="300" class="a-expander-collapsed-height a-row a-expander-container a-expander-partial-collapse-container" style="max-height:300px">
<div data-hook="review-collapsed" aria-expanded="false" class="a-expander-content reviewText review-text-content a-expander-partial-collapse-content">
<span>In all honesty I'm not sure why the price is quite as high ….</span>
</div>
				…</div>
			…</span>
		…</div>
	…</div>

Каждый интересующий вас фрагмент отзыва покупателя имеет свой уникальный класс: review-title-content для заголовка, review-text-content для основного текста и review-rating для рейтинга.  

Можно проверить, является ли класс на веб-странице уникальным и, если да, то воспользоваться им в качестве «простого селектора». Однако более надежным способом является все же использование дескриптора CSS, который останется уникальным, даже если в будущем тот же класс будет присвоен и некоторым другим элементам веб-страницы.

Просто извлеките CSS-дескриптор, щелкнув правой кнопкой мыши по элементу в DevTools и выбрав Copy Selector:

Процесс копирования селектора CSS для элемента из Инструментов разработчика в Chrome
Процесс копирования селектора CSS для элемента из Инструментов разработчика в Chrome

Вы можете определить свои три селектора следующим образом:

  • customer_review-R2U9LWUSIPY0GS > div:nth-child(2) > a.a-size-base.a-link-normal.review-title.a-color-base.review-title-content.a-text-bold > span для title  
  • customer_review-R2U9LWUSIPY0GS > div.a-row.a-spacing-small.review-data > span > div > div.a-expander-content.reviewText.review-text-content.a-expander-partial-collapse-content > span для body    
  • customer_review-R2U9LWUSIPY0GS > div:nth-child(2) > a:nth-child(1) > i.review-rating > span для rating *.review-rating был добавлен вручную для лучшей согласованности.  

CSS Selector vs XPath для веб-скрапинга

В этом учебнике мы решили использовать селектор CSS для идентификации элементов при веб-скрапинге. Другой популярный метод — использовать XPath, т.е. XML Path, который идентифицирует элемент через его полный путь в DOM.

Вы можете извлечь Xpath (полный путь к элементу в DOM), следуя той же процедуре, которая используется и для селекторов CSS. Например, название обзора является следующим:

/html/body/div[2]/div[3]/div[6]/div[32]/div/div/div[2]/div/div[2]/span[2]/div/div/div[3]/div[3]/div/div[1]/div/div/div[2]/a[2]/span 

Селектор CSS чуть быстрее, а XPath имеет немного лучшую обратную совместимость. За исключением этих небольших различий, выбор одного из них зависит больше от личных предпочтений, чем от их технических преимуществ.

Программное извлечение информации с веб-страницы

Хотя мы могли бы использовать для изучения веб-скрапинга консоль напрямую, вместо этого создадим сценарий для отслеживания и воспроизведения, и запустим его через консоль с помощью команды source().  

После создания скрипта первым шагом будет загрузка установленных библиотек:

library(”rvest”)
library(”tidyverse”)

После этого вы можете программно извлечь интересующий вас контент следующим образом. Сначала создайте переменную, в которой будет храниться URL для поиска:

HtmlLink <- "https://www.amazon.co.uk/Xbox-Elite-Wireless-Controller-2/dp/B07SR4R8K1/ref=sr_1_1_sspa?crid=3F4M36E0LDQF3"

Затем извлеките стандартный идентификационный номер Amazon (ASIN) из URL-адреса, чтобы использовать его в качестве уникального идентификатора продукта:

ASIN <- str_match(HtmlLink, "/dp/([A-Za-z0-9]+)/")[,2]

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

Теперь загрузите HTML-контент веб-страницы:

HTMLContent <- read_html(HtmlLink)

Функция read_html() является частью пакета xml2.

Если вы выведете контент с помощью функции print(), мы увидим, что он соответствует проанализированной нами ранее структуре HTML:  

{html_document}
<html lang="en-gb" class="a-no-js" data-19ax5a9jf="dingo">
[1] <head>\n<meta http-equiv="Content-Type" content="text/ht ...
[2] <body class="a-aui_72554-c a-aui_accordion_a11y_role_354 ...

Теперь вы можете извлечь три интересующих вас узла для всех отзывов о товаре на странице. Используйте дескрипторы CSS, предоставленные инструментами разработчика в Chrome и модифицированные для удаления идентификатора отзыва покупателя #customer_review-R2U9LWUSIPY0GS и соединителя «>» из строки; вы также можете воспользоваться функциями html_nodes() и html_text() в rvest для сохранения HTML-контента в отдельных объектах.  

Следующие команды извлекут заголовки обзоров:

review_title <- HTMLContent %>%
html_nodes("div:nth-child(2) a.a-size-base.a-link-normal.review-title.a-color-base.review-title-content.a-text-bold span") %>%
html_text()

Пример записи в review_title: «Очень хороший контроллер, хотя цена немного завышена».  

Приведенный ниже код извлечет «тело» обзора:

review_body <- HTMLContent %>%
html_nodes("div.a-row.a-spacing-small.review-data span div div.a-expander-content.reviewText.review-text-content.a-expander-partial-collapse-content span") %>%
html_text()

Пример записи в review_body начинается со слов “Честно говоря, я не уверен, почему цена…”.  

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

review_rating <- HTMLContent %>%
html_nodes("div:nth-child(2) a:nth-child(1) i.review-rating span") %>%
html_text()

Примером записи в review_rating является «4,0 из 5 звезд».  

Чтобы улучшить качество этой переменной, извлеките только оценку «4.0» и преобразуйте ее в int:

review_rating <- substr(review_rating, 1, 3) %>% as.integer()

Функция %>% обеспечивается за счет использования magrittr.

Настало время для экспорта полученного с помощью веб-скапинга контента в tibble для анализа данных. tibble представляет собой пакет R, который также входит в коллекцию tidyverse и используется для манипулирования и печати фреймов данных.  

df <- tibble(review_title, review_body, review_rating)

Итоговый фрейм данных выглядит следующим образом:

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

Наконец, отличной идеей будет рефакторинг кода в функцию scrape_amazon <- function(HtmlLink), что позволит привести его в соответствие к лучшим современным практикам и оптимизировать для масштабирования сразу на несколько целевых URL.    

Масштабирование на несколько URL-адресов

После составления скрапинг-шаблона вы можете создать с помощью веб-краулинга и веб-скрапинга список URL-адресов всех продуктов главных конкурентов на Amazon.  

При масштабировании на несколько URL-адресов необходимо описать технические требования приложения.

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

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

  • Пакетно или в режиме реального времени
  • Формат(ы) вывода, например, JSON, NDJSON, CSV или XLSX
  • Цель(и) вывода, например, электронная почта, API, webhook или облачное хранилище

Мы уже упоминали, что вы можете расширить возможности rvest с помощью polite для веб-скрапинга сразу нескольких интернет-страниц. polite создает и управляет сеансом сбора данных с веб-страниц при помощи трех основных функций, в полном соответствии с файлом robots.txt веб хоста, с использованием встроенного ограничителя скорости и кэшированием ответов:  

  • bow() создает сессию по сбору данных для определенного URL, т.е. представляет вас веб-хосту и запрашивает разрешение на веб-скрапинг.  
  • scrape() получает доступ к HTML-коду URL-адреса; вы можете передать эту функцию из rvest в html_nodes() и html_text(), чтобы получить необходимый контент.  
  • nod() обновляет URL сессии до следующей страницы без необходимости заново создавать сессию.  

Цитирую непосредственно с их сайта: «Три главных правила вежливого сеанса — спрашивать разрешение, не спешить и никогда не просить дважды».  

Следующий шаг: Pre-Built vs. Self-Built?

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

  • Команда специалистов с большим опытом извлечения данных
  • Команда инженеров DevOps с большим опытом управления прокси и обхода антиботов, позволяющим преодолевать любую CAPTCHA-защиту и работать с сайтами с ограниченным доступом.
  • Команда инженеров с опытом создания инфраструктуры по извлечению данных — пакетному или в режиме реального времени
  • Команда экспертов в области права в сфере законодательных требований по защите конфиденциальной информации (таких как GDPR и CCPA)

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

Как правило, пользователи прибегают к использованию следующего продвинутого функционала:

  1. Минимизируйте вероятность CAPTCHA и обнаружения ботов: Самый простой подход здесь — добавление случайного sleep(), чтобы избежать перегрузки веб-серверов и стандартных шаблонов запросов. Наиболее же эффективным подходом считается использование user_agent или прокси-сервера для распределения запросов между различными IP.  
  2. Веб-скрапинг сайтов с использованием Javascript: В нашем примере с Amazon URL-адрес не меняется при выборе конкретного варианта товара. Это приемлемо для отзывов, поскольку они являются общими, но не для характеристик продукта. Чтобы имитировать взаимодействие пользователей на динамических веб-страницах, можно использовать такой инструмент, как RSelenium, который позволяет автоматизировать навигацию по веб-браузеру.  

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

Web Scraper от Bright Data предоставляет шаблоны для множества веб-сайтов, оснащенных самыми современными функциями, включая продвинутый Amazon Scraper!  

More from Bright Data

Datasets Icon

Get immediately structured data

Access reliable public web data for any use case. The datasets can be downloaded or delivered in a variety of formats. Subscribe to get fresh records of your preferred dataset based on a pre-defined schedule.

Web scraper IDE Icon

Build reliable web scrapers. Fast.

Build scrapers in a cloud environment with code templates and functions that speed up the development. This solution is based on Bright Data's Web Unlocker and proxy infrastructure making it easy to scale and never get blocked.

Web Unlocker Icon

Implement an automated unlocking solution

Boost the unblocking process with fingerprint management, CAPTCHA-solving, and IP rotation. Any scraper, written in any language, can integrate it via a regular proxy interface.

Ready to get started?