см. Ниже мой код, который должен быть «улучшенной» функцией 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"])