Веб-парсинг с R — проще, чем Python

Давайте разработаем приложение для парсинга веб-страниц в реальном времени с R — намного проще, чем с Python

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

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

  • Нет доступного набора данных для необходимого анализа.
  • Общедоступного API нет

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

Если что-то не так, не делайте этого.

К счастью, некоторые веб-сайты созданы исключительно для отработки веб-скрейпинга. Один из них — books.toscrape.com, на котором, как следует из названия, перечислены составленные книги разных жанров:

Итак, давайте теперь поскребем этого ублюдка, ладно?

План атаки

Откройте веб-страницу, щелкните любые две категории (боковая панель слева) и проверьте URL-адрес. Вот наш выбор:

https://books.toscrape.com/catalogue/category/books/travel_2/index.html
https://books.toscrape.com/catalogue/category/books/mystery_3/index.html

Что общего у этих URL-адресов? Все, кроме выделенной жирным шрифтом части. Это сама категория. Понятия не имею, в чем дело с нумерацией, но так оно и есть. Каждая страница содержит список книг, а отдельная книга выглядит так:

См. также:  Функция активации для искусственной нейронной сети

Наша задача — собрать информацию по каждой книге в категории. Для этого требуется немного знаний HTML, но это простой язык разметки, поэтому я не вижу здесь проблемы.

Мы хотим очистить:

  • Заголовок — свойство h3 ›a› title.
  • Рейтинг — атрибут p.star-rating ›class.
  • Цена — div.product_price ›div.price_color› text.
  • Доступность — div.product_price ›div.instock› text
  • URL книги — div.image_container ›a› href свойство
  • URL эскиза — свойство div.image_container ›img› src

Теперь вы все знаете, так что давайте начнем со скребка.

Выскабливание книг

Пакет rvest используется в R для выполнения задач очистки веб-страниц. Он очень похож на dplyr, известный пакет анализа данных, из-за использования оператора конвейера и поведения в целом. Мы знаем, как добраться до определенных элементов, но как реализовать эту логику в R?

Вот пример того, как очистить названия книг в категории путешествия:

library(rvest)

url <- 'https://books.toscrape.com/catalogue/category/books/travel_2/index.html'
titles <- read_html(url) %>% 
  html_nodes('h3') %>%
  html_nodes('a') %>% 
  html_text()

Разве не все было просто? Аналогичным образом мы можем очистить все остальное. Вот сценарий:

library(rvest)
library(stringr)

titles <- read_html(url) %>% 
  html_nodes('h3') %>%
  html_nodes('a') %>% 
  html_text()

urls <- read_html(url) %>%
  html_nodes('.image_container') %>% 
  html_nodes('a') %>% 
  html_attr('href') %>% 
  str_replace_all('../../../', '/')

imgs <- read_html(url) %>% 
  html_nodes('.image_container') %>%
  html_nodes('img') %>%
  html_attr('src') %>%
  str_replace_all('../../../../', '/')

ratings <- read_html(url) %>% 
  html_nodes('p.star-rating') %>% 
  html_attr('class') %>% 
  str_replace_all('star-rating ', '')

prices <- read_html(url) %>% 
  html_nodes('.product_price') %>% 
  html_nodes('.price_color') %>% 
  html_text()

availability <- read_html(url) %>% 
  html_nodes('.product_price') %>% 
  html_nodes('.instock') %>% 
  html_text() %>% 
  str_trim()

Потрясающие! В качестве последнего шага давайте склеим все это в один фрейм данных:

scraped <- data.frame(
  Title = titles, 
  URL = urls, 
  SourceImage = imgs, 
  Rating = ratings, 
  Price = prices, 
  Availability = availability
)

На этом вы можете закончить статью и завершить ее, но мы можем построить еще кое-что из этого — простое и легкое в использовании веб-приложение. Давай сделаем это дальше.

См. также:  Как читать прямоугольник, окруженный пробелами, используя readxl

Веб-приложение для парсинга

В R есть фантастическая библиотека для разработки веб-приложений и информационных панелей — Shiny. Его гораздо проще использовать, чем что-либо подобное в Python, поэтому мы будем его придерживаться. Для начала создайте новый R-файл и вставьте внутрь следующий код:

library(shiny)
library(rvest)
library(stringr)
library(glue)

ui <- fluidPage()

server <- function(input, output) {}

shinyApp(ui=ui, server=server)

Это шаблон, который требуется каждому приложению Shiny. Затем давайте настроим пользовательский интерфейс. Нам понадобятся:

  • Заголовок — просто большой жирный текст поверх всего (необязательно)
  • Боковая панель — содержит раскрывающееся меню для выбора жанра книги.
  • Центральная область — отображает вывод таблицы после очистки данных.

Вот код:

ui <- fluidPage(
  column(12, tags$h2('Real-time web scraper with R')),
  sidebarPanel(
    width=3,
    selectInput(
      inputId='genreSelect',
      label='Genre',
      choices=c('Business', 'Classics', 'Fiction', 'Horror', 'Music'),
      selected='Business',
    )
  ),
  mainPanel(
    width=9,
    tableOutput('table')
  )
)

Далее нам нужно настроить функцию сервера. Он должен переназначить наши красиво отформатированные входные данные на часть URL (например, «Business» на «business_35») и очистить данные для выбранного жанра. Мы уже знаем, как это сделать. Вот код для функции сервера:

server <- function(input, output) {
  output$table <- renderTable({
    mappings <- c('Business' = 'business_35', 'Classics' = 'classics_6', 'Fiction' = 'fiction_10',
                  'Horror' = 'horror_31', 'Music' = 'music_14') 
    
    url <- glue('https://books.toscrape.com/catalogue/category/books/', mappings[input$genreSelect], '/index.html')
    
    titles <- read_html(url) %>% 
      html_nodes('h3') %>%
      html_nodes('a') %>% 
      html_text()
    
    urls <- read_html(url) %>%
      html_nodes('.image_container') %>% 
      html_nodes('a') %>% 
      html_attr('href') %>% 
      str_replace_all('../../../', '/')
    
    imgs <- read_html(url) %>% 
      html_nodes('.image_container') %>%
      html_nodes('img') %>%
      html_attr('src') %>%
      str_replace_all('../../../../', '/')
    
    ratings <- read_html(url) %>% 
      html_nodes('p.star-rating') %>% 
      html_attr('class') %>% 
      str_replace_all('star-rating ', '')
    
    prices <- read_html(url) %>% 
      html_nodes('.product_price') %>% 
      html_nodes('.price_color') %>% 
      html_text()
    
    availability <- read_html(url) %>% 
      html_nodes('.product_price') %>% 
      html_nodes('.instock') %>% 
      html_text() %>% 
      str_trim()
    
    data.frame(
      Title = titles, 
      URL = urls, 
      SourceImage = imgs, 
      Rating = ratings, 
      Price = prices, 
      Availability = availability
    )
  })
}

Вот и все — теперь мы можем запустить приложение и проверить его поведение!

См. также:  #pragma mark и настраиваемые предупреждения и ошибки в XCode

Именно то, что мы хотели — просто, но все же вполне понятно. Давайте подведем итоги в следующем разделе.

Напутственные слова

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

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

Спасибо за прочтение.

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

Первоначально опубликовано на https://www.betterdatascience.com 19 октября 2020 г.

Понравилась статья? Поделиться с друзьями:
IT Шеф
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: