Разделение веб-скребков на разные куски в R - PullRequest
0 голосов
/ 16 марта 2019

см. Ниже мой код, который должен быть «улучшенной» функцией glassdoor-webscraper на Github для R (https://github.com/mguideng/gdscrapeR/blob/master/R/get_reviews.R).). Целью всего этого было бы разбить процесс на отдельные этапы, где Я всегда могу возобновить очистку веб-страниц, вместо того чтобы надеяться, что соединение будет существовать достаточно долго, чтобы загрузить обзоры всей компании. Кроме того, я также добавил возможность очистить несколько компаний.

Конечной целью будет создание одного CSV-файла для каждой компании, где я использую rbind для объединения различных частей.

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

library(dplyr)
library(gdscrapeR)
library(tictoc)
library(stringr) 
library(httr)  #get HTML document: GET()
library(xml2)  #convert to XML document: read_html()
library(rvest) #select & extract text from XML: html_nodes() & html_text() html_attr()
library(purrr) #iterate scraping and return data frame: map_df()

df2 <- data.frame(rev.date = NULL,
                  rev.sum = NULL,
                  rev.rating = NULL,
                  rev.title = NULL,
                  rev.pros = NULL,
                  rev.cons = NULL,
                  rev.helpf = NULL,
                  source.url = NULL,
                  source.link = NULL,
                  source.iden = NULL)


test = data.frame(ID = c("E12799", "E6484"),Company = c("Julius_Baer", "Coop"))

big4 <- data.frame(ID = c("E2784", "E2763", "E8450", "E2867"),Company = c("EY", "Deloitte", "PWC", "KPMG"))


get_reviews <- function(companyNum) {


  # Set URL
  baseurl <- "https://www.glassdoor.com/Reviews/Company-Reviews-"
  sort <- ".htm?sort.sortType=RD&sort.ascending=true"

  # Nested function for getting max results
  get_maxResults <- function(companyNum) {
    totalReviews <- xml2::read_html(httr::GET(paste(baseurl, companyNum, sort, sep = ""))) %>%
      html_nodes(".tightVert.floatLt strong, .margRtSm.margBot.minor") %>%
      html_text() %>%
      sub(" reviews", "", .) %>%
      sub(",", "", .) %>%
      as.integer()
    return(ceiling(totalReviews/10))
  }


  # Message
  Sys.sleep(2)
  cat("\nNumber of web pages to scrape: ")
  maxResults <- get_maxResults(companyNum)
  Sys.sleep(6)
  cat(maxResults)

  # Nested functions to collapse newline (<br>) within pros & cons corpus body of text
  collapse_html_text <- function(x, collapse = "\n", trim = F) {
    UseMethod("collapse_html_text")  # parse xml use method:
  }

  collapse_html_text.xml_nodeset <- function(x, collapse = "\n", trim = F) {
    vapply(x, collapse_html_text.xml_node, character(1),
           trim = trim, collapse = collapse)
  }

  collapse_html_text.xml_node <- function(x, collapse = "\n", trim = F) {
    paste(xml_find_all(x, ".//text()"), collapse = collapse)
  }


  lower = round(seq(1, maxResults, by = ceiling(maxResults/10)))[-1]

  lower = c(1,lower, maxResults)

  upper = round(seq(ceiling(maxResults/10), maxResults, by = ceiling(maxResults/10)))[-1]

  upper = c(round(ceiling(maxResults/10)),upper,maxResults)

  constraints = data.frame(lower, upper)

  for (row in 1:nrow(constraints)){


    # Nested function to get info (scrape based on CSS selectors pattern)
  get_selectors <- function(pg, i) {
    data.frame(rev.date = html_text(html_nodes(pg, ".date.subtle.small, .featuredFlag")),
               rev.sum = html_text(html_nodes(pg, ".reviewLink .summary:not([class*='toggleBodyOff'])")),
               rev.rating = html_attr(html_nodes(pg, ".gdStars.gdRatings.sm .rating .value-title"), "title"),
               rev.title = html_text(html_nodes(pg, "span.authorInfo.tbl.hideHH")),
               rev.pros = collapse_html_text(html_nodes(pg, ".description .row:nth-child(1) .mainText:not([class*='toggleBodyOff'])")),
               rev.cons = collapse_html_text(html_nodes(pg, ".description .row:nth-child(2) .mainText:not([class*='toggleBodyOff'])")),
               rev.helpf = html_text(html_nodes(pg, ".tight")),
               source.url = paste(baseurl, companyNum, "_P", i, sort, sep = ""),
               source.link = html_attr(html_nodes(pg, ".reviewLink"), "href"),
               source.iden = html_attr(html_nodes(pg, ".empReview"), "id"),
               stringsAsFactors = F)
  }

  # Message
  Sys.sleep(3)
  cat("\nStarting")

  # Nested function to get data frame
  df <- purrr::map_df(constraints[row,"lower"]:constraints[row,"upper"], function(i) {
    Sys.sleep(sample(seq(0, 1, by = 0.01), 1))  # be polite
    cat(" P", i, sep = "")
    pg <- xml2::read_html(httr::GET(paste(baseurl, companyNum, "_P", i, sort, sep = "")))
    get_selectors(pg, i)
  })


  df <- rbind(df)

  }
  # Return
  Sys.sleep(0.1)
  return(data.frame(df))

}

df3 <- get_reviews(companyNum = test[row, "ID"])
...